다음은 기본 컴파일과 JIT 컴파일의 차이점 만 비교하며 특정 언어 또는 프레임 워크의 세부 사항은 다루지 않습니다. 이를 넘어서 특정 플랫폼을 선택해야하는 합당한 이유가있을 수 있습니다.
네이티브 코드가 더 빠르다고 주장 할 때 네이티브 컴파일 된 코드와 JIT 컴파일 된 코드 의 일반적인 사용 사례 에 대해 이야기하고 있습니다. 여기서 JIT 컴파일 된 응용 프로그램의 일반적인 사용은 사용자가 즉시 수행해야합니다 (예 : 먼저 컴파일러를 기다리는 중). 이 경우 JIT 컴파일 코드가 네이티브 코드와 일치하거나 이길 수 있다고 누군가가 똑바로 주장 할 수 있다고 생각하지 않습니다.
어떤 언어 X로 작성된 프로그램이 있다고 가정하고 네이티브 컴파일러로 컴파일하고 다시 JIT 컴파일러로 컴파일 할 수 있다고 가정 해 봅시다. 각 작업 흐름에는 동일한 단계가 있으며 (Code-> Intermediate Representation-> Machine Code-> Execution)으로 일반화 할 수 있습니다. 두 가지의 큰 차이점은 사용자가 보는 단계와 프로그래머가 보는 단계입니다. 기본 컴파일을 사용하면 프로그래머는 실행 단계를 제외한 모든 것을 볼 수 있지만 JIT 솔루션을 사용하면 실행 외에도 머신 코드에 대한 컴파일이 사용자에게 표시됩니다.
A가 B보다 빠르다는 주장 은 사용자가 본 것처럼 프로그램을 실행하는 데 걸린 시간을 말합니다 . Execution 단계에서 두 코드가 동일하게 수행된다고 가정하면 JIT 작업 흐름이 사용자에게 느리다고 가정해야합니다. 머신 코드에 대한 컴파일 시간 T도 T> 0이어야합니다. , JIT 작업 흐름이 기본 작업 흐름과 동일하게 수행 될 가능성이있을 경우, 사용자는 코드 실행 시간을 줄여서 실행 + 머신 코드로의 컴파일이 실행 단계보다 낮도록해야합니다. 기본 작업 흐름 즉, JIT 컴파일에서 원시 컴파일보다 코드를 더 잘 최적화해야합니다.
그러나 실행 속도를 높이기 위해 필요한 최적화를 수행하기 때문에 기계 코드 단계로 컴파일하는 데 더 많은 시간을 소비해야하므로 최적화 된 코드의 결과로 절약 할 때마다 실제로 손실됩니다. 컴파일에 추가합니다. 즉, JIT 기반 솔루션의 "느림"은 JIT 컴파일 시간이 추가 된 것이 아니라 해당 컴파일에서 생성 된 코드가 기본 솔루션보다 느리게 수행됩니다.
예제를 사용하겠습니다 : 레지스터 할당. 메모리 액세스는 레지스터 액세스보다 수천 배 느리므로 가능한 한 레지스터를 사용하고 가능한 한 적은 메모리 액세스를 원하지만 레지스터 수가 제한되어 있으며 필요할 때 상태를 메모리에 넘겨야합니다 레지스터. 계산에 200ms가 걸리는 레지스터 할당 알고리즘을 사용하면 결과적으로 2ms의 실행 시간을 절약 할 수 있습니다. JIT 컴파일러에 시간을 최대한 활용하지는 않습니다. 고도로 최적화 된 코드를 생성 할 수있는 Chaitin 알고리즘과 같은 솔루션은 적합하지 않습니다.
JIT 컴파일러의 역할은 컴파일 시간과 생성 된 코드의 품질 사이에서 최상의 균형을 유지하는 것입니다. 그러나 사용자를 기다리지 않기 때문에 빠른 컴파일 시간에 큰 편향이 있습니다. JIT의 경우 코드 최적화에서 시간이 지남에 따라 원시 컴파일러가 바인딩되지 않기 때문에 실행중인 코드의 성능이 느려집니다. 따라서 최상의 알고리즘을 자유롭게 사용할 수 있습니다. JIT 컴파일러에 대한 전체 컴파일 + 실행이 기본적으로 컴파일 된 코드의 실행 시간 만 이길 수있는 가능성은 사실상 0입니다.
그러나 VM은 단순히 JIT 컴파일에만 국한되지 않습니다. Ahead-of-time 컴파일 기술, 캐싱, 핫 스와핑 및 적응 형 최적화를 사용합니다. 따라서 성능이 사용자가 보는 것임을 주장을 수정하고 프로그램을 실행하는 데 걸리는 시간으로 제한합니다 (AOT가 컴파일되었다고 가정). 우리는 실행 코드를 네이티브 컴파일러와 동등하게 만들 수 있습니다. VM에 대한 큰 주장은 특정 함수가 얼마나 자주 실행될 수 있는지와 같은 실행중인 프로세스의 정보에 더 많은 정보에 액세스 할 수 있기 때문에 원시 컴파일러보다 우수한 품질의 코드를 생성 할 수 있다는 것입니다. 그런 다음 VM은 핫 스와핑을 통해 가장 필수적인 코드에 적응 형 최적화를 적용 할 수 있습니다.
이 인수에는 문제가 있습니다. 프로파일 가이드 최적화 등은 VM 고유의 것으로 가정하지만 사실이 아닙니다. 프로파일 링을 사용하여 응용 프로그램을 컴파일하고 정보를 기록한 다음 해당 프로파일을 사용하여 응용 프로그램을 다시 컴파일하여 원시 컴파일에도 적용 할 수 있습니다. 코드 핫 스와핑은 JIT 컴파일러 만이 할 수있는 것이 아니며, 네이티브 코드에 대해서도 할 수 있다는 점을 지적 할 가치가 있습니다. JIT 기반 솔루션은 더 쉽게 사용할 수 있고 개발자에게는 훨씬 쉽습니다. 가장 큰 질문은 VM이 네이티브 컴파일이 할 수없는 정보를 제공 할 수 있습니까? 그러면 코드 성능이 향상 될 수 있습니까?
나는 그것을 스스로 볼 수 없다. 프로세스가 더 복잡하지만 일반적인 VM의 기술 대부분을 네이티브 코드에도 적용 할 수 있습니다. 마찬가지로 AOT 컴파일 또는 적응 형 최적화를 사용하는 VM에 기본 컴파일러의 최적화를 다시 적용 할 수 있습니다. 실제로는 기본적으로 실행되는 코드와 VM에서 실행되는 코드의 차이가 생각보다 크지 않다는 것입니다. 그들은 궁극적으로 같은 결과를 가져 오지만 거기에 도달하기 위해 다른 접근법을 취합니다. VM은 반복적 인 접근 방식을 사용하여 최적화 된 코드를 생성하며, 네이티브 컴파일러는 처음부터이를 기대하고 반복적 접근 방식으로 개선 할 수 있습니다.
C ++ 프로그래머는 시작부터 최적화가 필요하다고 주장 할 수 있으며 VM이이를 수행하는 방법을 알아낼 때까지 기다리지 말아야합니다. VM의 현재 최적화 수준이 네이티브 컴파일러가 제공 할 수있는 것보다 열등하기 때문에 현재 기술에서는 유효 할 수 있습니다. 그러나 VM의 AOT 솔루션이 개선되는 경우에는 항상 그렇지는 않습니다.