Section 2. JS엔진

Wendy·2021년 2월 7일
0

Udemy - JavaScript: The Advanced Concepts

Section 2. Javascript Foundation

JS 엔진

  • 사람(JS파일 작성) --> JS엔진(번역) --> 컴퓨터 (0101..이해)
  • 엔진은 종류가 많다 (V8, SpiderMonkey, Chakra...)
    . V8 : 2008년 / c++ / chrome, nodejs / 구글이 크롬 만들면서 엔진(v8)을 자체제작
    . SpiderMondy: 첫 JS엔진(1995년 최초의 JS와 함께 탄생) for Netscape by Brendan Eich). Mozilla Gecko, Firefox 에서 사용중
    . Charkra : for Edge by MS
    . Javascript Core : 애플 개발. 사파리, react native에서 사용중
  • ECMAScript 엔진 : 누구나 (Gecko등을 이용해) 엔진을 만들수있지만 난립하지않도록 표준 제시

JS 엔진 기본 작동

0) JS파일 입력
1) Parser : token으로 분리(Parse Tree 생성?)
2) AST(Abstract Syntax Tree)
3) Interpreter : 한줄씩 해석 -> ByteCode 생성 (기계어보다는 느림)
4) Profiler : 최적화 할 게 있을지 모니터링
5) Compiler : 최적화
6) Optimized code : 최적화된 기계어(101011...) 전달하여 Bytecode 부분 대체
---> interpreter로 일단 바로 실행하고, compiler로 점진적으로 효율화
---> 이걸 배워야하는 이유 : compiler는 완벽한게 아니기 때문에 내가 작성하는 코드가 컴파일러를 헷갈리지 않게, 유리하게 잘 사용할 수 있도록 하면 좋으니까

Interpreter vs Compiler

  • interpreter :
    . high-low 사이의 중단단계 언어로 번역
    . 프로그램 실행시 한줄씩 바로 변환(번역빠름) vs 최적화가 없고 기계어가 아님(실행느림)
    . JS는 브라우저 사용자가 화면을 기다리므로 interpreter로 개발됨
    . 오류 발생 전까지는 실행하고 그 이후에 중단되어 사용자가 조금이라도 더 볼수있음
  • compiler :
    . 전체를 파악하고 기계어로 변환 (기계에 종속되는 언어)
    . 전체를 읽고 번환(번역느림) vs 최적화되고, 기계어임 (실행 빠름)
    . 전체를 읽기때문에 미리 오류 파악 가능, 오류 있으면 실행 안됨
    . 목적코드 생성으로 메모리는 더 쓰지만 실행은 빠름
  • 두개를 결합하자: JIT Compiler (Just In Time) - v8엔진

다른 언어들은?

. 실행파일(.exe) : 주로 c++ 작성 후 (실행환경에 맞는) 기계어로 컴파일 -> 기계에서 실행
. java파일 : java 작성 > Bytecode 컴파일(JVM : JV기계...기계어로의 컴파일!) > JVM이 사용자 기계에 맞게 interpreting

엔진 최적화를 고려한 코딩

  • 사용 주의 : eval() / arguments / for in / with / delete
  • v8 최적화 기법 : Hidden classes / Inline caching

//eval(), with는 엔진에게 scope 혼란을 줄수 있어 최적화가 어려움

hidden class

JS는 객체 생성 후 속성을 추가 할 수있는 동적타이핑 언어로, 속성을 사전형으로 저장한다. 따라서 컴파일 시 속성의 메모리 오프셋을 결정하는 고정적타이핑 언어들(예 - JAVA)에 비해 검색비용이 든다. 이에 v8에서는 hidden class 방식을 사용하는데, 객체에 새로운 속성이 추가될때마다 새로운 히든클래스로 전환된다.

inline caching

동일한 메소드를 동일한 유형의 객체에서 반복적으로 호출하는 점에 착안해 만들어진 기법. v8엔진은 최근에 호출된 메서드에 매개변수로 전달된 객체에 대한 타입을 캐시로 유지하는데, 동일한 히든클래스를 가진 객체가 두번이상 동일 메서드를 호출하면, 사용될 속성의 오프셋을 확인하기 위해 객체를 탐색하는 과정을 생략할 수 있다. 최적화 코드를 이용하던중 다른 타입의 객체가 메서드를 호출하면, 다시 de-optimized된 코드로 바꿔서 진행하므로 이를 고려한 코딩 필요!

최적화를 위한 전략

  • 같은 순서로 객체의 속성을 인스턴스 화 할것 -> 그래야 같은 히든클래스를 사용하게 됨 -> 그래야 인라인 캐싱을 사용할수있음.
  • 가능한 처음부터 생성자에 모든 속성을 할당
  • 하나의 array에 하나의 타입만 넣어줄것
  • array에 값을 띄엄띄엄 넣지말것 + 배열 요소를 삭제하지말것 (중간중간 빈 array는 hash table이나 마찬가지임)

Web Assembly

처음부터 JS를 컴파일 해서 기계어로 만들었음 실행이 빠르잖아?
1) 브라우저에서 컴파일하려면 브라우저가 엄청 빨라야한다 - 1995년엔 느렸다
2) 바이너리 코드를 실행시키기 위한 (브라우저가 모두 동의하는) 표준이 있어야 한다 - 1995년은 브라우저 경쟁의 시대였으니 통합 불가였고, 지금까지도 브라우저별로 작동하는거 다다르다

그러나 이제 달라질것!
2017년 Web Assembly(표준 Binary 실행 포맷)가 탄생했다.

읽어본 글

같은 강의 기록

엔진 설명

v8 최적화

profile
개발 공부중!

0개의 댓글

관련 채용 정보