둘러보기
js란?
- javascript는 웹페이지를 위한 프로그래밍 언어
- js로 작성한 프로그램인 script는 html 안에서 작성할 수 있음
- 브라우저 및 JavaScript engine이 포함된 디바이스에서 동작 가능
- 브라우저는 자바스크립트 가상 머신(엔진)을 내장
- chrome: V8
- firefox: SpiderMonkey
- MS edge: ChakraCore
- safari: SquirrelFish
- 엔진은 스크립트를 파싱 후 기계어로 컴파일, 이후 실행
브라우저 보안
- 저수준 조작 허용 X
- 메모리, CPU 등
- 브라우저를 대상으로 만들었기 때문
- OS가 지원하는 기능을 브라우저가 직접 쓰지 못함
- 디바이스와의 인터랙션은 사용자의 허가 안에서 수행
- Same Origin Policy
- 페이지 간의 데이터 교환은 상호 동의 하에 가능
- 한 창에서 다른 창을 열 때 (도메인, 프로토콜, 포트)가 같으면 접근 가능
- 서버, 모바일에서도 쓸 수 있음
장점
- HTML/CSS 와의 통합
- 단순함
- 브라우저의 지원 (기본 언어로 쓰임)
단점
Rust
Rust란?
- (메모리)안정성과 성능, 쾌적한 사용성을 목표로한 언어.
- undefined behavior를 컴파일 과정에서 발견
- 오버플로, 허가받지 않은 메모리 접근(더블 프리, 널 역참조), divided by zero 등
- 컴파일을 통과한 언어는 안전하다고 할 수 있음
장점
- C/C++에서 발생할 수 있는 (메모리, 포인터 관련) 문제를 컴파일 타임에 잡음
- 안전한 병렬 프로그래밍 (메모리 안정성에 쓰이는 제약을 동시성 문제에도 적용)
- 빠른 성능
단점
WebAssembly
WebAssembly란?
- js로 충분하지 않은 속도를 해결하기 위해 등장
- 모바일 등 리소스가 제한된 상황
- 게임, AI 등 성능이 필요한 경우
- 여러 언어로 작성된 코드를 컴파일 하여 네이티브에 가까운 속도로 실행될 수 있게 함
- 여러 플랫폼에서 실행 가능
- 샌드박싱된 실행 환경에서 안전하도록 설계
- js와 상호 보완
핵심 개념
- 모듈
- 브라우저에서 실행가능한 기계어로 컴파일된 웹 어셈블리 바이너리
- stateless
- winodws와 workers 간의 명시적 공유 가능
- 필수 섹션
- Type
- 모듈에 정의되거나 import한 함수들의 시그니처
- Function
- Code
- 선택 섹션
- export
- 다른 어셈블리 모듈, js에서 사용 가능한 인스턴스 생성
- Import
- 다른 어셈블리 모듈, js에서 사용 가능한 인스턴스 지정
- Memory
- 모듈이 사용하는 메모리
- WebAssembly의 저수준 메모리 접근 명령에 의해 읽거나 쓸수 있는 크기 조절 가능한 바이트 ArrayBuffer
- c/c++, rust에서 사용하는 heap을 시뮬레이션하기 위해 배열 버퍼 사용
- 배열의 인덱스들은 메모리의 주소처럼 쓰임
- Start
- Global
- Table
- 안정성과 이식성을 위해 raw 바이트로 저장되지 않는 A resizable typed array of references
- js 객체 같이 wasm 모듈 외부의 값을 맵핑
- Data
- Element
인스턴스
- WebAssembly 모듈이 실행 시간에 사용하는 상태 (메모리, 테이블, impoted values)
- js api를 사용해 wasm의 모듈, 메모리, 테이블, 인스턴스 생성 가능
- wasm 코드의 실행 상태 관리
- wasm 코드를 js로, js 코드를 wasm으로 내보낼 수 있음
js
- js 파일은 텍스트로 되어있어 전부 읽은 후 컴파일 해야 실행 가능
- parse - decode - compile & optimize - (reoptimize) - exe - GC
- JIT
- js 엔진에 모니터 추가
- 코드 실행 빈도 파악 (warm -> hot)
- Baseline compiler
- 함수가 warm 해지면 컴파일 후 정보 저장 (모니터가 파악)
- 함수는 stub으로 컴파일 (줄번호와 타입을 인덱스로 사용)
- optimization compiler
- hot인 코드를 모니터가 최적화하여 컴파일러에게 전송
- 컴파일러는 더 빠른 코드를 생성하여 저장
- 컴파일된 코드는 실행 전 유효성 체크
- 유효하지 않다면 최적화된 코드 폐기
- 폐기되었다면 역최적화 (인터프리터 or base compiler 이후 상태
- js의 최적화는 성능 저하를 일으킬 수 있음
- JIT가 같은 코드에 대해 최적화-역최적화를 반복한다면 최적화를 안하는 게 이득
- 작업 중 오버헤드 및 메모리 낭비가 있을 수 있음
wasm
- wasm도 컴파일 해야하지만 앞서 이진 파일로 컴파일된 상태
- decode - compile & optimize - execute
- WebAssembly
- 실제 기계가 아닌 가상(개념적) 기계를 위한 언어
- wasm의 명령어를 virtual instruction 라고도 함
- HW 기계어에 맵핑되지는 않음
- js 보다 기계어에 가까움
- 브라우저는 wasm을 갖고 기계의 어셈블리를 위한 hop을 만든다.
- IR: 작성한 코드를이식성을 위해 LLVM을 위한 IR로 변환
- IR을 wasm 으로 변환하여 wasm 파일을 최종적으로 얻음
- 형태는 어셈블리와 비슷(hexadecimal)
속도가 빠른 이유
- js
- parsing: source를 인터프리터가 실행할 수 있는 형태로 변환
- 브라우저에서 AST로 변환
- 일부만 해석하고 사용하지 않는 코드는 stub으로 만들어 둠
- compile & optimization: baseline, optimization compiler 수행시간
- re-optimization: 역최적화, 기본코드로 되돌리는 작업
- execute: 실행 시간( 타입이 항상 동일 하다고 가정하고 코드 최적화, 이 동작에 맞춰주면 빠른 js 코드 가능 )
- GC: 불필요한 메모리 삭제
- 위 작업은 작은 단위로 수행 (한 번에 전체 X)
- wasm
- fetch: js 보다 간결하여 데이터 가져오는 속도가 빠름
- parsing: wasm은 중간 표현 형식이기 때문에 변환 필요 없음, decode 및 에러 체크
- compile & optimization: 앞서 살펴본 여러 최적화 작업이 필요 없어 빠름
- 어떤 타입인지 확인학 위해 실행해 볼 필요 없음
- 정적 타이핑 되어 컴파일 된 상태
- re-optimization: 필요 없는 단계
- excute: 일반적으로 빠름
- GC: 없음. 메모리는 프로그래머의 역량
참조
js: https://ko.javascript.info/
rust: 짐 블랜디 & 제이슨 오렌도프 & 리어노라 틴달, 프로그래밍 러스트 (2nd ed.)
wasm
rust로 webgpu를 사용해서 브라우저에 동작하도록 만들어 보는 건 어떻습니까