Chrome V8은 어떻게 작동합니까? 그리고 왜 JavaScript가 JIT 컴파일되지 않았습니까?


19

인터프리터 / 컴파일러를 연구 한 후 JIT 컴파일, 특히 Chrome의 V8 Javascript 엔진을 우연히 발견했습니다.

내 질문은-

  1. 표준 통역보다 어떻게 더 빠를 수 있습니까?
  2. JIT 컴파일이 왜 처음에는 사용되지 않았습니까?


나의 현재 이해

  1. 모든 Javascript 프로그램은 소스 코드 로 시작하여 실행 방법에 관계없이 궁극적으로 기계 코드 로 변환됩니다 . JIT 컴파일해석
    모두이 경로를 따라야하므로 어떻게 JIT 컴파일이 더 빨라질 수 있습니까 (JOT가 AOT 컴파일과 달리 시간 제약이 있기 때문에)?

  2. JIT-Compilation은 Wikipedia의 JIT-Compilation Article에 기반한 비교적 오래된 혁신으로 보입니다 .

"초기 출판 된 JIT 컴파일러는 일반적으로 1960 년 McCarthy에 의해 LISP에서 작동하는 데 기인합니다 ."

"Smalltalk (c. 1983 )는 JIT 컴파일의 새로운 측면을 개척했습니다. 예를 들어, 기계 코드로의 변환은 요청에 따라 수행되었으며 결과는 나중에 사용하기 위해 캐시되었습니다. 메모리가 부족하면 시스템은이 코드 중 일부를 삭제하고 재생성합니다. "다시 필요할 때"

그렇다면 왜 Javascript가 처음 부터 해석 되었습니까?


나는 매우 혼란스러워서 이것에 대해 많은 연구를 해왔지만 만족스러운 답변을 찾지 못했습니다.

명확하고 간결한 답변을 부탁드립니다. 그리고 통역사, JIT 컴파일러 등에 대한 추가 설명이 필요하다면 감사하겠습니다.


2
# 2와 # 3는 대답 할 수 있지만 "Chrome V8 엔진은 어떻게 작동합니까?" 자격이 없으면 너무 광범위합니다. 정답은 V8 소스 코드에 대한 링크입니다. V8에 대해 좀 더 구체적인 질문을 하시겠습니까? (아니라면 질문의 해당 부분을 제거하는 것이 가장 좋습니다)
Ixrec

두 번째로, # 1을 요구하는 유일한 요점은 # 2를 이해하는 것이 었으므로 제거하겠습니다. 입력 해 주셔서 감사합니다.
Anton Paras

이것은 다른 답변에서는 언급되지 않았지만 JIT 컴파일은 어렵습니다. JIT 컴파일으로 인한 오류로 인해 오류 대신 segfault가 발생하기 때문에 간단한 작업이 아닙니다. 콘솔에서 오류를 발생시키는 대신 프로그램이 충돌합니다. 예, gdb에 익숙한 유능한 C 프로그래머에게는 문제가되지 않습니다. 그러나 gdb에 익숙한 거의 모든 유능한 C 프로그래머는 다른 프로젝트를 수행하기 위해 돈을 받는다 Perl 및 Ruby와 같은 일부 다른 언어에는 여전히 주류 JIT 인터프리터가 없습니다.
slebetman

궁금한 경우. 프로그래밍 언어의 핵심 개발자 / 유지 업체 관점에서 이에 대해 이야기하고 있습니다. 몇 년 동안 나는 Ferite 프로그래밍 언어를 유지하기 위해 고용되었습니다. 우리가 원하는 위시리스트 중 하나는 JIT를 구현하는 것이 었습니다. 그것은 일어나지 않았다 – 우리는 대신에 갔다. 페이스 북 덕분에 PHP는 최근에 JIT 컴파일러 (HVVM)를 확보했다.
slebetman

답변:


43

짧은 대답은 JIT는 초기화 시간이 길지만 장기적으로 훨씬 빠르며 JavaScript는 원래 장기적으로 의도되지 않았다는 것입니다.

90 년대에는 웹 사이트의 일반적인 JavaScript가 헤더에있는 하나 또는 두 개의 함수와 onclick속성 등에 직접 포함 된 소수의 코드에 해당합니다. 어쨌든 사용자가 큰 페이지로드 지연을 기대할 때 정상적으로 실행됩니다. 매우 기본적인 양식 검증 또는 모기지이자 계산기와 같은 작은 수학 유틸리티를 생각하십시오.

필요에 따라 해석하는 것이 훨씬 간단하고 오늘날의 사용 사례에 완벽하게 적합한 성능을 제공했습니다. 장기적으로 성능이 좋은 것을 원한다면 플래시 또는 Java 애플릿을 사용했습니다.

2004 년 Google지도는 JavaScript를 많이 사용하는 최초의 킬러 앱 중 하나였습니다. JavaScript의 가능성에 눈을 뜨게되었지만 성능 문제도 강조했습니다. 구글은 브라우저가 자바 스크립트 성능을 개선하도록 장려하기 위해 시간을 보냈으며, 결국 경쟁이 최고의 동기 부여가되고 브라우저 표준 표에서 최고의 자리를 차지할 것이라고 결정했다. 그 결과 2008 년 Chrome과 V8이 출시되었습니다. 이제 Google지도가 등장한 지 11 년이 지난 지금, JavaScript를 기억하지 못하는 새로운 개발자가 이런 종류의 작업에 적합하지 않다고 생각합니다.

기능이 있다고 가정 해보십시오 animateDraggedMap. 해석하는 데 500ms, JIT 컴파일에는 700ms가 걸릴 수 있습니다. 그러나 JIT 컴파일 후 실제로 실행하는 데 100ms 밖에 걸리지 않을 수 있습니다. 90 년대이고 함수를 한 번만 호출 한 다음 페이지를 다시로드하는 경우 JIT는 전혀 가치가 없습니다. 오늘이고 animateDraggedMap수백 또는 수천 번 호출하는 경우 초기화시 200ms가 더 걸리지 않으며 사용자가 맵을 드래그하기 전에 장면 뒤에서 수행 할 수 있습니다.


2

런타임에 무슨 일이 일어나고 있는지 이해하면, 컴파일 시간 이전에 알려진 것보다 더 빠르게 실행되거나 더 잘 컴파일 될 수 있도록 코드를 변경하거나 코드를 해석 할 수 있습니다.

이것에 대해 상당히 말할 수 있습니다. 상당한 양의 연구가 필요합니다. 차이점이해하기에 주어진 대답과 비교하여 팔레스를 작성하기 시작한 전통적인 설명 : 전통적인 해석기, JIT 컴파일러, JIT 해석기 및 AOT 컴파일러


간단히 말해서, JavaScript는 JIT를 위해 처음 컴파일되거나 검토되지 않았습니다. 왜냐하면 JIT는 복잡하거나 중요한 것이 아니기 때문입니다.

Java Script 의 원래 의도 는 웹 페이지에서 Java 애플릿에 연결하는 것이 었습니다. 일부 단추를 클릭하거나 양식 필드에 값을 입력 한 다음 Java 애플릿 메소드에서 작업을 수행하는 기능은 JavaScript 코드에서 애플릿 메소드 호출 에서 볼 수 있습니다 . 애플릿에서 JavaScript 코드를 호출 하는 다른 방법으로 JavaScript를 통해 가능했습니다 .

JavaScript의 원래 의도는 애플릿과이를 포함하는 HTML 페이지를 링크하는 것이 었습니다. 이러한 작은 작업의 경우 큰 성능이 필요하지 않습니다 (성능을 원하면 JIT 된 애플릿 메소드를 호출하십시오).

Netscape가 JavaScript로 자체 언어로 상당한 작업을 시작하고 개발을 위해이를 홍보 한 후에야 Netscape Enterprise Server의 서버 측 JavaScript 를 포함하여 자바 스크립트가 심각한 목표로 밝혀졌습니다. . 필요한 도구를 유용하게 사용하려면 수년이 걸렸습니다.


1
아니요, Javascript는 Java와 관련이 없습니다. 그리고 Java 애플릿은 JVM 바이트 코드입니다.
바 실레 Starynkevitch

@BasileStarynkevitch JavaScript는 햄릿 페이지에서 Java 애플릿과 함께 작동하도록 설계되었습니다. HTML DOM과 Java 객체에 포함 된 메소드 사이의 접착제 역할을합니다. Java가 아니며 결코 Java가 아닙니다.

JavaScript는 원래 ECMAScript (또는 이와 유사한 것)라고하며 Java와 관련이 없습니다. JavaScript라고하는 방법은 관심있는 사람들을위한 별도의 연구 주제입니다. 이로 인해 혼란이 계속되고 있습니다.
quick_now

1
@quickly_now는 여전히 tc39.github.io/ecma262입니다
caub

예. 그리고 내가 이상한 점을 지적했을 때 나는 그것을 위해 하향 투표를 받았다!
quick_now

1

JIT는 변수 유형을 모르는 경우 빠른 기계 코드를 생성 할 수 없으므로 JavaScript에 빠릅니다.

유형 정보가 없으면 계산 비용이 많이 듭니다. 예를 들어

x + y

x와 y에 대해 아무것도 모른다면 꽤 복잡합니다. 정수, 복식, 문자열 또는이 계산에 부작용이있는 개체 일 수도 있습니다. 정적 타이핑이 없기 때문에 비용이 많이 듭니다.

JIT (Just-In-Time) 컴파일을 통해 런타임 정보를 사용하여 더 빠른 계산으로 전환 할 수 있습니다. 런타임시 V8은 변수 유형을 추적합니다. 위의 코드가 예를 들어 문자열로 여러 번 실행되면 컴파일러는 문자열 연결에 대한 훨씬 간단한 명령을 실행할 수 있습니다. 따라서 컴파일러가에 도달하면 x + yx 및 y의 여러 유형으로 분기되는 많은 코드를 실행하는 대신 컴파일러가 문자열이 있는지 신속하게 확인한 다음 문자열을 구체적으로 연결하는 몇 줄의 기계 코드를 실행합니다.

예를 들어, C ++에서는 변수를 선언해야했기 때문에 컴파일러는 x와 y의 유형을 미리 알고 있습니다. 따라서 코드를 실행하기 전에 문자열을 연결하기위한 최적화 된 기계 코드를 생성 할 수 있습니다.


0

1) 표준 통역보다 더 빠를 수있는 방법은 무엇입니까? 생각해 볼만한 예는 다음과 같습니다. ApplicationCompiled와 ApplicationInterpreted라는 두 가지 응용 프로그램이 있다고 가정합니다. 이 두 프로그램 모두 정확히 동일한 작업을 수행하고 동일한 소스 코드를 공유합니다. ApplicationCompiled는 컴파일하는 데 6 초가 걸립니다.

시나리오 A의 타이밍은 다음과 같습니다.

  • ApplicationCompiled의 경우 : 4 초
  • ApplicationInterpreted의 경우 : 12 초

따라서 전체 ApplicationCompiled에서 시나리오 A (6 초 컴파일, 4 초 실행)를 실행하는 데 10 초가 걸리고 ApplicationInterpreted가 실행되는 데 총 12 초가 걸립니다. 나는 당신을 보여줄 구체적인 예를 가지고 있지 않으며, 어떤 경우에 위의 내용이 사실인지 잘 모르겠습니다. 또한 해석과 컴파일러의 지능에 크게 의존합니다.

분명히 이것은 매우 간단하지만 imho와 동일한 아이디어가 JIT 컴파일 / 해석에 적용될 수 있습니다. 다음 질문은 "이 지점이 JIT 컴파일 또는 해석되어야 하는지를 어떻게 낮은 비용으로 결정합니까?"입니다. 나는 내 리그에서 나왔습니다 :)

2) JIT 컴파일이 왜 처음에는 사용되지 않았습니까? 모릅니다. 그러나 JavaScript와 같이 최적화하기 어려운 언어를 이러한 고급 기술에 적용 할 수 있도록하기 위해서는 사용 가능한 진행 상황의 성숙도와 자원의 문제 일뿐입니다. 당시에는 과일이 많이 줄었을 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.