Inside the V8 engine + 5 tips on how to write optimized code

들어가기

이 글은 How JavaScript works: inside the V8 engine + 5 tips on how to write optimized code 을 번역한 글입니다.

개요

자바스크립트 엔진은 자바스크립트 코드를 실행하는 프로그램 또는 인터프리터를 말합니다. 자바스크립트 엔진은 표준적 인터프리터로 구현될 수 있고 또한 자바스크립트 코드를 바이트 코드로 컴파일하는 just-in-time 컴파일러로 구현 가능합니다.

아래 목록은 자바스크립트 엔진을 구현한 유명한 프로젝트들 입니다.

  • V8 - 오픈소스, 구글에서 개발, C++ 로 작성됨
  • Rhino - 모질라 파운데이션에서 관리, 오픈소스, Java 로 개발됨
  • SpiderMonkey - 최초의 자바스크립트 엔진, 이전에 넷스케이프 네비게이터에 사용되었고, 현재는 파이어폭스가 사용중
  • JavaScriptCore - 오픈소스, 니트로라는 이름으로 알려져 있으며 사파리를 위해 애플이 개발함
  • KJS - KDE 의 엔진으로 KDE 프로젝트의 컨커러 웹 브라우저를 위해 해리포텐이 개발
  • Chakra(JScript9) - 인터넷 익스플로러
  • Chakra(JavaScript) - 파이크로소프트 엣지
  • Nashorn - 오픈 JDK 의 일환으로 오픈소스이며 오라클 자바언어와 톱그룹으로 작성
  • JerryScript - 사물 인터넷을 위한 경량 엔진

V8 엔진을 왜 만들었는가?

V8 엔진은 구글이 만들었으며 오픈소스이고 C++로 제작되었다. 구글 크롬에서 사용하는 중이다. 그리고 다른 엔진들과의 차이점은 노트 js 의 런타임으로 사용된다는 점이다.

V8

V8 은 웹 브라우저 내부에서 자바스크립트 실행 속도의 개선을 위해 처음으로 기획되었다. 속도 향상을 위해 V8 엔진은 인터프리터를 사용하지않고 자바스크립트 코드를 더 효율적인 머신 코드로 번역한다. JIT (Just-In-Time) compiler를 구현함으로써 코드를 실행할 때에 자바스크립트 코드를 머신 코드로 컴파일 하는데, 이는 SpiderMonkey 나 모질라의 Rhino 같은 현대적 자바스크립트 엔진에서도 마찬가지이다. V8 엔진의 가장 큰 차이점은 바이트코드와 다른 중간코드를 생성하지 않는다는 것입니다.

V8 은 원래 두개의 컴파일러를 가지고 있었다.

V8 의 5.9 버전이 출시되기 전에는, V8 에서 두개의 컴파일러를 사용하였다.

  • full-codegen - 간단하고 매우 빠른 컴파일러로 단순하고 상대적으로 느린 머신 코드를 생성
  • Crankshaft - 좀더 복잡한 최적화 컴파일러로 높은 최적화 코드를 생성

V8 엔진은 또한 내부적으로 여러 개의 쓰레드를 사용한다.

  • 메인 쓰레드는 코드를 가져와서 컴파일하고 실행하는 역할을 한다.
  • 또한 컴파일을 위한 별도의 쓰레드가 있어, 이 쓰레드가 코드를 최적화 하는동안 메인 쓰레드는 계속해서 코드를 수행할 수 있다.
  • 프로파일러 쓰레드는 어떤 메소드에서 사용자가 많은 시간을 보내는지 런타임에게 알려주고 Crankshaft 가 이들을 최적화할 수 있게 해준다.
  • Garbage Collector sweeps 을 처리하기 위한 다른 몇개의 쓰레드가 있다.

자바스크립트 코드를 처음으로 실행할 때 V8 엔진은 full-codegen을 사용하여 파싱된 자바스크립트 코드를 변형 없이 직접 머신코드로 번역한다. 이를 통해 머신 코드의 실행을 매우 빠르게 시작할 수 있다. V8 은 이와 같이 중간 바이트 코드를 이용하지 않기 때문에 인터프리터가 필요 없어진다.

코드가 어느정도 실행된 뒤 다음 프로파일러 쓰레드는 충분한 데이터를 얻게 되고 어떤 메소드를 최적화할지 알 수 있게 된다.

다음으로, Crankshaft가 다른 쓰레드에서 최적화를 시작한다. Crankshaft 는 자바스크립트의 추상구문트리를 static single-assignment (SSA)로 번역하는데 이것을 Hydrogen이라고 부른다. 대부분의 최적화가 이 단계에서 이뤄진다.

Inlining

첫 번째 최적화는 가능한 많은 코드를 인라이닝 하는 것이다. 인라이닝은 호출 지점(함수가 호출된 곳의 호출 위치)을 호출한 함수의 내용으로 바꾸는 과정이다. 이 간단한 단계를 통해 다음 최적화가 더욱 의미있게됩니다.

V8

히든 클래스

자바스크립트는 프로토타입 기반의 언어이다. 클래스는 없으며 객체는 복제 과정을 통해 생성된다. 자바스크립트는 또한 동적언어이므로 객체가 생성된 후에도 속성을 쉽게 추가하거나 삭제 가능하다.