태초의 FullCodegen이 있으라.
처음 V8이 만들어질 때, FullCodegen 컴파일러가 자바스크립트를 컴파일하고 최적화까지 했습니다. 하지만 최적화의 성능은 그렇게 좋지 못하고 복잡한 자바스크립트의 코드는 최적화 효율이 떨어졌습니다. 그래서 구글에서는 보다 복잡하고 더 효율적인 최적화를 위해 Crankshaft를 만들게 되었습니다.
최적화의 전문가 Crankshaft
크랭크샤프트(Crankshaft)는 V8 엔진의 옵티마이저로, JavaScript 코드의 실행 속도를 향상시키기 위해 설계된 고성능 최적화 컴파일러입니다. V8이 코드 실행하면서 프로파일러를 통해 최적화가 필요한 코드 정보를 수집합니다. Crankshaft는 이렇게 수집된 프로파일링 정보를 기반으로 런타임에서 높은 성능의 머신 코드를 동적으로 생성하여 JavaScript 코드를 최적화합니다.
Crankshaft의 몰락
Crankshaft는 ECMAScript 6 (ES6)가 나오면서 사라지게 되었습니다. Crankshaft는 ES6를 지원할 수 없었습니다. 왜냐하면 ES6 특정 기능을 최적화할 수 없어 이러한 기능을 사용하는 코드의 실행 시간이 느려지는 결과를 가져오게 되었죠. 그리고, 복잡한 제어 흐름을 가진 코드는 최적화하는 것에 어려움이 있었고, 이로 인해 일부 유형의 코드의 실행 시간이 느려지는 문제가 발생했습니다.
요약하면 수많은 레거시 때문에 사라지게 된 것 같습니다. Crankshaft는 많은 최적화 단계를 가지고 있었습니다. 그래서 ES6와 같이 계속 자바스크립트가 발전하면서 계속 여러 기능을 지원해야 했기 때문에 몇가지를 수정하면 그 후의 단계에서 악영향을 미치는 등 문제를 만들었습니다.
뜨거워진 코드를 식혀라! TurboFan!
2015년 Crankshaft는 사라지고 그 자리를 대신하기 위해 TurboFan이 탄생했습니다.
TurboFan은 V8의 파이프라인이 개선되면서 각 최적화 단계가 잘 모듈화되어 만들어졌습니다. 그래서 Crankshaft에 비해 각 코드 간 의존성도 줄어들고 수정과 교체에 용이해졌습니다.
TurboFan의 최적화 기술
TurboFan은 V8 엔진의 최적화 컴파일러로, 효율적인 머신 코드를 생성하기 위해 여러 최적화 기술을 사용합니다. TurboFan이 사용하는 최적화 기술은 다양합니다.
- 인라이닝 (Inlining)
- 루프 최적화 (Loop optimization)
- 타입 특수화 (Type specialization)
- 이스케이프 분석 (Escape analysis)
- 히든 클래스 (hidden class)
- 인라인 캐싱 (inline caching)
- 레지스터 할당 (Register allocation)
…
이 중 개인적으로 중요하다고 생각한 몇가지를 소개하려 합니다.
인라이닝 (Inlining)
인라이닝은 함수 호출 명령을 실행하는 대신 호출되는 함수의 실제 코드로 함수 호출을 대체하는 작업입니다. 즉, 함수 호출 프레임의 오버헤드를 제거하고 메모리 액세스 수를 줄이는 것입니다.
인라이닝은 자주 호출되는 작은 함수에 효과적입니다. 함수 호출은 CPU는 반환 주소 및 기타 상태를 스택에 푸시하고 함수 코드 위치로 점프하는 등 CPU에서 함수호출에 필요한 일련의 과정들을 가지고 있습니다. 자주 호출하는 작은 함수를 인라이닝을 하는 것은 이 과정들을 생략하기 때문에 그만큼 최적화할 수 있는 것입니다.
그러나 인라이닝도 단점이 있습니다. 인라이닝은 결과 머신 코드의 크기를 증가시켜 프로그램의 메모리 사용량에 영향을 줄 수 있습니다. 또한 인라인된 코드는 사용될 때마다 다시 생성해야 하므로 인라인은 코드 캐싱의 효율성을 감소시킬 수 있습니다. 결과적으로 인라인은 이점과 비용의 균형을 맞추기 위해 신중하게 사용해야 합니다.
인라인 캐싱 (inline caching)
인라인 캐싱은 자주 접근하는 프로퍼티의 결과를 캐시하여 프로퍼티 접근 속도를 높입니다. 런타임에 수행해야 하는 조회 및 함수 호출 수를 줄여 JavaScript 코드의 성능을 크게 향상시킬 수 있습니다.
함수가 호출되거나 object.property나 object["property"]와 같은 프로퍼티에 접근할 때, 인라인 캐시를 확인하여 이전에 해당 코드를 실행했는지 확인합니다. 만약 확인했다면 이전에 실행했던 결과를 인라인 캐시에서 꺼내 사용합니다.
루프나 자주 사용하는 코드, 반복 함수 호출, 그리고 프로퍼티 접근을 수행하는 코드에 특히 효과적입니다.
히든 클래스 (Hidden class)
히든 클래스는 아래의 링크처럼 이전 포스트에 대해 다룬적이 있습니다.
https://wooncloud.tistory.com/105
자바스크립트 객체 관리와 V8엔진 히든클래스
이 글은 모던 자바스크립트 Deep Dive를 보고 공부한 내용입니다. 자바스크립트에서 객체는 복합적인 자료구조입니다. 객체 내부에 있는 property의 수는 개수가 정해지지 않아, 객체의 크기도 정해
wooncloud.tistory.com
자바스크립트에서 새 객체를 만들면 V8 엔진은 이전 객체를 히든 클래스로 숨기고 새로운 객체에 이 히든 클래스의 정보와 구조를 가져가도록 할당합니다.
객체의 히든 클래스는 개발자에게 표시되지 않으며 객체 프로퍼티 접근을 최적화하기 위해 V8 엔진에서 사용됩니다. TurboFan은 히든 클래스 객체 프로퍼티 접근 패턴을 분석하고 런타임에 필요한 히든 클래스 전환 수를 줄입니다. 히든 클래스를 최적화하면서 TurboFan은 자바스크립트 코드의 전반적인 성능을 향상시키고 효율적인 머신 코드를 생성할 수 있습니다.
다음 이야기
V8은 2017년 WebAssembly를 지원할 수 있게 되었습니다.
그렇다면 WebAssembly가 무엇이고 V8이 WebAssembly를 어떻게 작동시킬 수 있을까요?
다음편은 WebAssembly와 V8의 LiftOff입니다.
'개발 아카이브 > 개발 관련 지식' 카테고리의 다른 글
V8 Liftoff와 웹 어셈블리: 웹 성능을 향상시키는 강력한 조합 (0) | 2023.04.20 |
---|---|
[노션 API] 노션 API 연동으로 데이터베이스 사용하기 (1) | 2023.04.09 |
자바스크립트 엔진인 V8에 대해 알아보자 (1) | 2023.02.26 |
정규식을 이용한 공격 - ReDos (0) | 2022.12.24 |
Postman 대신 사용하는 VS Code API Test Extention - Thunder Client (1) | 2022.11.13 |