Skip to content

JavaScript 엔진의 최적화 과정은 어떻게 이루어지는가? (feat. JIT) #2

@luke0408

Description

@luke0408

궁금한 점

What:

  • JavaScript 엔진의 최적화 기준
    • JIT 컴파일 과정에서 "어떤 코드가 최적화할 가치가 있는지" 엔진이 어떻게 판단하는가?
    • 자주 실행되는 코드가 어떤 방식으로 감지되고 최적화되는가? => Hot Code 최적화에 대하여
    • 특정 코드 패턴이 JIT 최적화에 긍정적인 영향을 미치는가?
    • Hoisting이 JIT 최적화에 미치는 영향이 있는가?

  • JIT 최적화 실패 (Deoptimization)의 원인
    • 디옵티마이제이션(Deoptimization)이 발생하는 주요 원인은 무엇인가?
    • JavaScript 코드에서 최적화를 방해하는 특정 패턴이 있는가?
    • 엔진이 어떤 경우에 최적화된 코드를 폐기하고 다시 바이트코드 실행 방식으로 되돌리는가?

  • JIT 컴파일러의 두 가지 방식 (Baseline JIT vs Optimizing JIT)
    • Baseline JIT과 Optimizing JIT은 각각 어떤 역할을 수행하는가?
    • JavaScript 엔진이 어떤 기준으로 Optimizing JIT을 적용하는가?
    • Baseline JIT에서 Optimizing JIT으로 전환되는 과정은 어떻게 이루어지는가?

Why:

#1 을 공부하면서 JavaScript Engine의 대략적인 모습을 이해할 수 있었다. 그 중 JIT와 컴파일 과정에 대한 Optimization과 관련된 내용을 접할 수 있었는데, 실제로 JS 코드는 처음 컴파일 될 때와 이후에 코드가 바뀌고 다시 컴파일 될 때 방법이 다르다고 한다. 이런 컴파일 과정의 최적화가 어떻게 처리되고 분기가 일어나는지 전체적인 과정에 대해서 이해해보고자 한다.

추측해보기

What I Already Know:

#1 을 통해 학습한 내용을 기반으로 이야기를 진행해보겠습니다.

Preliminary Thoughts:

[JIT 최적화 기준에 대하여]

  • Q1: 최적화할 코드 패턴을 어떻게 감지할까?

    • 개념의 이름으로 미루어 보아 JIT은 처음 컴파일될 때 Baseline JIT이 실행되고, 이후 실행 패턴을 분석하여 Optimizing JIT이 적용되는 단계적 방식일 것이라 생각한다.
    • Baseline JIT과의 비교를 통해 자주 실행되는 코드(Hot Code)를 감지하고, 이를 Optimizing JIT에서 최적화할 수 있다.
    • 이런 식으로 코드의 변경이 감지 될 때마다 비교를 하는 로직이라고 한다면, 전체 컴파일 코드를 가지고 있는 것이 아니라 변경점만을 빠르게 비교하기 위한 git diff 파일 같은 것을 사용하고 있지 않을까?
  • Q2: 최적화할 코드의 특징은 무엇이 있을까?

    • 반복적으로 실행되는 코드(Hot Code), 일관된 데이터 타입을 유지하는 코드, 함수 호출이 일정한 패턴을 가지는 경우, 예외 발생 가능성이 낮은 코드 처럼 코드 내부의 변경 가능성이 낮은 코드는 최적화가 쉬울 것이다.
    • 즉 반대로 변수의 타입이 로직 중에 매번 바뀐다거나 하는 코드는 최적화가 어려울 것이라 생각한다.
  • Q3: 특정 코드 패턴이 최적화에 유리할까?

    • 변수 타입이 일관되게 유지되는 코드, 동적 속성 추가가 적은 객체가 최적화되기 쉬울 것이다.

[JIT 최적화 실패 원인에 대하여]

  • Q4: JIT 최적화된 코드가 예상과 다르게 동작하면 어떻게 될까?

    • JIT이 최적화한 코드가 실행 중 예상과 다르게 동작하면 Deoptimization(최적화 해제)이 발생할 가능성이 있다.
    • 변수 타입이 실행 도중 변경되면 JIT이 이를 감지하고 최적화를 해제할 가능성이 있다.
  • Q5: 어떤 상황에서 최적화가 해제될까?

    • 이미 최적화가 된 코드에 변경이 생기면 최적화가 해제될 것이다.
    • ex)
      • Hot Code로 최적화된 코드가 실행 도중 타입 변경이 발생할 때
      • 함수의 실행 패턴이 예측과 다르게 변경될 때
      • 객체 속성이 동적으로 추가되거나 삭제될 떄

[JIT의 두 가지 방식에 대하여]

  • Q6: 두 가지 JIT 방식은 왜 필요할까?

    • Baseline JIT을 초기에 코드가 처음 JIT를 통해 실행될 때 사용된 코드라고 하자,
    • Optimizing JITHot Code를 감지하여 기계어로 변환하여 실행 속도를 높이는 역할을 할 것이다.
    • 즉, Baseline JIT 없이 바로 Optimizing JIT을 적용할 수 없을 것이다.
  • Q7: 두 방식의 우선순위는 어떻게 결정될까?

    • Baseline JIT이 실행된 후, 특정 코드가 일정 횟수 이상 실행되면 Optimizing JIT이 개입할 것이다.
    • JIT이 Hot Code를 감지하는 기준실행 횟수, 데이터 타입의 일관성, 예외 발생 여부 등을 기반으로 한다고 가정한다면, 특정 코드가 실행 중 타입 변경이나 예외 발생 등의 문제가 감지될 때 다시 Baseline JIT으로 되돌아가는 식으로 동작 할 것이다.
    • 즉, 동작의 우선도는 Optimizing이 높을 것이고 기능의 우선도는 Baseline이 높을 것이다

Checklist: Essential Guidelines to Verify Before Posting

  • Clear Title: 제목이 문제의 핵심을 명확하고 간결하게 요약하고 있나요?
  • Detailed Background: 문제의 배경, 학습 동기, 현재 이해한 내용을 충분히 설명하였나요?
  • Reproducible Example (if applicable): 코드나 재현 가능한 예제가 필요한 경우, 최소한의 예제를 포함하였나요?
  • Readability: 질문이 읽기 쉽도록 헤더, 목록, 코드 블록 등을 적절히 사용하였나요?

Originally posted by @luke0408 in #1

Metadata

Metadata

Assignees

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions