190107 TIL JS33 - JavaScript Engines

» 1막, TIL (Today I Learned)

JavaScript Engines

알고리즘 스터디에서 javascript 33을 공부하는 sub 스터디(?)를 만들었다.
Kaka와 함께 준비하는 주제는 [11. JavaScript Engines]
(https://github.com/leonardomso/33-js-concepts#11-javascript-engines)이다.

JSConfEu 2017에서 Franziska Hinkelmann가 관련 주제로 스피치한 영상을 보고 전체적인 개념을 파악할 수 있었다.


Franziska Hinkelmann: JavaScript engines - how do they even? | JSConf EU 2017

  • 현재 여러 개의 JavaScript Engine이 있으며 경쟁이 있으면 더 나은 결과물을 낼 수 있기 때문에 좋다.
    • Browser : Chakra, JavaScriptCore, Spidermonkey, V8
    • Node.js: Chakra, V8, SpiderNode
    • Electron: V8
    • IoT: Duktape, JerryScript
  • JS = dynamically typed vs. C++ = statically typed

      JavaScript
      var x = 17;
    
      C++
      int x = 17
    

    개발자 입장에선 JavaScript가 유용하고 쉽지만, 컴파일러 입장에서는 주어지는 정보가 너무 없기 때문에 기계어(machine code)로 변환하기 어렵다. 그렇기 때문에 C++이 컴파일이 용이한데, JavaScript도 방대한 라이브러리를 사용해도 꽤 빠른 편이다. 어떻게 이게 가능할까?

  • JavaScript가 빠를 수 있는 이유는 JavaScript engine이 JIT(Just In Time) compilation을 사용하기 때문이다.

      Just In Time (JIT) Compilation
       : Generate machine code during runtime, not ahead of time (AOT).
       : 컴파일을 먼저하고 코드를 실행하는 것이 아니라, 이 두 가지 스텝을 섞어서 코드를 리컴파일(recompile)하는 데 필요한 정보들을 사용하는 것
    
       cf. C++ : AOT, 먼저 컴파일 후 실행
    
  • 현대 컴파일러는 적어도 두 개 이상의 컴파일러를 가지고 있는데, 그 중 하나는 optimising compiler다.
    optimising compiler는 hot function을 recompile 한다. 즉, 자주 사용하는 함수(hot function)는 optimising compiler가 recompile 하여 속도를 빠르게 할 수 있는 것이다. 만약, recompile 됐던 함수의 input type이 달라지면 de-optimise 되어 baseline compiler로 돌아간다.

  • Optimizing compiler는 이전의 사용된 type 정보를 사용하므로 type을 바꾸지 않는 것이 좋다!
    (Optimizing compiler uses previously seen type information - don’t change types!)

      compile -> run a few times -> optimise(assuming certain conditions) -> run the optimised code -> if conditions fail, go back to the basic code
    

    image

    ** AST(Abstract Syntax Tree): 추상 구문 트리, 추상 구문 트리는 컴파일러에 널리 사용되는 자료 구조인데, 이는 프로그램 코드의 구조를 표현하는 프로퍼티이기 때문이다. AST는 일반적으로 컴파일러의 구문 분석 단계의 결과물이다. 컴파일러가 요구하는 여러 단계를 통해 프로그램의 중간 표현의 역할을 하며 컴파일러의 최종 결과물에 대해 강력한 영향을 준다. <위키백과>

    ** Baseline Compiler(인터프리터)는 바이트코드를 빠르게 생성할 수 있으나 비효율적, but Optimizing Compiler는 시간은 걸려도 효율적인 기계코드를 생성함

  • V8

    image

    Baseline Compiler = Ignition
    Optimizing Compiler = TurboFan
    Machine code = Bytecode