JVM이 JIT 컴파일 된 코드를 캐시하지 않는 이유는 무엇입니까?


107

Sun의 표준 JVM 구현은 코드가 몇 번 실행 된 후 거의 네이티브 실행 속도를 얻기 위해 바이트 코드에 매우 정교한 최적화를 적용합니다.

문제는 왜이 컴파일 된 코드가 동일한 함수 / 클래스의 후속 사용 중에 사용하기 위해 디스크에 캐시되지 않는 것입니까?

현재로서는 프로그램이 실행될 때마다 JIT 컴파일러가 미리 컴파일 된 코드 버전을 사용하지 않고 새로 시작됩니다. 이 기능을 추가하면 바이트 코드가 본질적으로 해석 될 때 프로그램의 초기 실행 시간이 크게 향상되지 않습니까?


4
이 문제를 논의하는 스레드 : javalobby.org/forums/thread.jspa?threadID=15812
miku

2
그러나 확실한 답을 얻을 가능성이없는 질문입니다.
bmargulies 2010 년

1
"중요한"부스트에 대해 확신 할 수 없습니다. 메모리에서 JIT하는 대신 디스크에서 JITted 항목을로드해야하기 때문입니다. 속도를 높일 수 있지만 사례별로 다릅니다.
R. Martinho Fernandes

1
모두에게 훌륭한 답변을 주셔서 감사합니다! 모든 답변이 똑같이 유효
했으므로이 문제

당신이 저를 요구하는 경우에이 : 좋은 질문입니다
알프레드

답변:


25

@MYYN이 게시 한 링크의 잘라 내기 및 붙여 넣기에 의존하지 않고, 이는 JVM이 수행하는 최적화가 데이터 패턴과 코드 패턴을 기반으로하는 정적이 아니라 동적이기 때문이라고 생각합니다. 이러한 데이터 패턴은 애플리케이션의 수명 동안 변경되어 캐시 된 최적화가 최적 수준보다 낮을 수 있습니다.

따라서 저장된 최적화가 여전히 최적인지 여부를 확인하는 메커니즘이 필요합니다.이 시점에서 즉시 다시 최적화 할 수 있습니다.


6
... 또는 당신은 단지로 지속성을 제공 할 수있는 옵션 역량 강화 - 오라클의 JVM이하는 것처럼, 고급 프로그래머 들이 응용 프로그램의 성능 및 그들은 단지 최적화 알고 패턴이되어 있지 자신의 책임하에 변화를. 왜 안돼?!
Alex Martelli

2
아마 그만한 가치가 없기 때문입니다. SUN, IBM, BEA 모두 성능 JVM에 대해 가치가 있다고 생각하지 않았다면 그럴만 한 이유가있을 것입니다. 아마도 그들의 RT 최적화는 오라클보다 빠르기 때문에 오라클은이를 캐시합니다.
skaffman

9
저장된 최적화를 시작점으로 삼아 이전 실행에서 배운 것을 사용하는 것은 어떨까요? 거기에서 JIT는 평소와 같이 재 최적화 작업을 할 수 있습니다. 종료시 해당 코드는 다시 유지되고 다음 실행에서 새로운 시작점으로 사용될 수 있습니다.
Puce 2012-07-25

1
@Puce 내가 생각할 수있는 유일한 이유는 AFAIK가 최적화 된 코드를 실행하여 프로파일 링 통계를 얻지 못한다는 것입니다. 당신은 개선 할 수있는 방법이 없습니다 ... 것 그래서
maaartinus

1
개인적으로 "이는 정확히 동일한 JVM, 동일한 데이터 등에서 만 유효하고 그렇지 않으면 무시 될 것입니다"라는 모든 경고와 함께 "실행 사이에 JIT 프로파일 링 정보를 유지"옵션으로 괜찮을 것입니다. 이것이 구현되지 않은 이유와 관련하여 JIT 시드 데이터를 유지하고 유효성을 검사하는 복잡성이 너무 많아 다른 프로젝트에서 리소스를 가져 오지 못할 것으로 예상합니다. 이것과 Java 8 lambda + streams 사이의 선택을 감안할 때 나는 차라리 후자를 갖고 싶습니다.
Thorbjørn Ravn Andersen

25

오라클의 JVM 은 실제로 문서화되어 있습니다.

컴파일러는 Oracle JVM의 클래스 분석 모델을 활용하여 데이터베이스 호출, 세션 또는 인스턴스에서 컴파일 된 Java 메소드를 선택적으로 지속 할 수 있습니다. 이러한 지속성은 의미 상 Java 코드가 변경되지 않은 것으로 알려진 세션 또는 인스턴스간에 불필요한 재 컴파일의 오버 헤드를 방지합니다.

모든 정교한 VM 구현이 유사한 옵션을 제공하지 않는 이유를 모르겠습니다.


8
다른 정교한의 JVM은 경적을 울리고있는 큰 기업이 없기 때문에 :)에 가게 물건에 편리 RDBMS
skaffman

와! 즉, 컴파일이 때때로 캐시됩니다. 이것은 좋은 소식입니다!
Sandeep Jindal

IBM의 J9도 문서화되어 있습니다.
user314104

9
이 Oracle JVM은 Oracle이 Sun을 구입할 때 다운로드 한 것이 아니라 Oracle Database 내부의 JVM입니다.
Thorbjørn Ravn Andersen 2015

14

기존 답변에 대한 업데이트-Java 8에는이를 해결하기위한 JEP가 있습니다.

=> JEP 145 : 캐시 컴파일 된 코드 . 새 링크 .

매우 높은 수준에서 명시된 목표는 다음과 같습니다.

대규모 Java 애플리케이션의 시작 시간을 개선하기 위해 이전 실행에서 컴파일 된 원시 코드를 저장하고 재사용합니다.

도움이 되었기를 바랍니다.


3
이 기능은 최종 릴리스에 포함 되지 않았습니다 .
assylias 2014 년

5

Excelsior JET 에는 2001 년에 릴리스 된 2.0 버전부터 캐싱 JIT 컴파일러가 있습니다. 또한 AOT 컴파일러는 모든 최적화를 사용하여 캐시를 단일 DLL / 공유 개체로 다시 컴파일 할 수 있습니다.


3
예,하지만 질문은 표준 JVM, 즉 Sun의 JVM에 관한 것이 었습니다. Java 및 기타 캐싱 JVM에 대한 여러 AOT 컴파일러가 있다는 것을 잘 알고 있습니다.
Chinmay Kanchi

0

JVM 구현에 어떤 식 으로든 관여하지 않는 실제 이유를 모르지만 몇 가지 그럴듯한 이유를 생각할 수 있습니다.

  • Java의 아이디어는 write-once-run-anywhere 언어이며, 클래스 파일에 미리 컴파일 된 내용을 넣는 것은 일종의 위반입니다 (물론 실제 바이트 코드가 여전히 존재하기 때문에 "종류"만 있음).
  • 동일한 코드를 여러 번 사용하기 때문에 클래스 파일 크기가 증가합니다. 특히 여러 다른 JVM에서 동일한 프로그램을 실행하는 경우 (다른 버전을 다른 JVM으로 간주 할 때 실제로 드물지 않습니다. 정말해야합니다)
  • 클래스 파일 자체는 쓰기가 불가능할 수 있습니다 (확인하기가 매우 쉽습니다).
  • JVM 최적화는 부분적으로 런타임 정보를 기반으로하고 다른 실행에서는 적용 가능하지 않을 수 있습니다 (여전히 약간의 이점을 제공해야 함).

하지만 저는 정말로 추측하고 있습니다. 보시다시피 제 이유 중 어떤 것도 실제 쇼 스토퍼라고 생각하지 않습니다. 나는 Sun이이 지원을 우선 순위로 생각하지 않는다고 생각하며, 습관적으로이 작업을 수행하면 사람들이 Java 클래스 파일이 실제로 각 VM에 대해 별도의 버전이 필요하다고 생각하게 할 수도 있기 때문에 내 첫 번째 이유가 진실에 가깝다고 생각합니다. 크로스 플랫폼.

내가 선호하는 방법은 실제로 이와 같은 작업을 미리 명시 적으로 수행하는 데 사용할 수있는 별도의 바이트 코드-네이티브 변환기를 사용하여 특정 VM에 대해 명시 적으로 빌드 된 클래스 파일을 생성하는 것입니다. 다른 VM에서도 실행할 수 있습니다. 그러나 그것은 아마도 내 경험에서 비롯된 것 같습니다. 저는 대부분 Java ME를 해왔는데, Java 컴파일러가 컴파일에 대해 더 똑똑하지 않다는 점이 정말 아픕니다.


1
실제로 원래 의도 (클래스 파일에 속성으로 JIT 코드를 저장)였습니다.
TofuBeer

@TofuBeer : 확인 감사합니다. 나는 그것이 사실일지도 모른다고 생각했지만 (그것이 내가했을 것입니다) 확신하지 못했습니다. 가능한 이유에서 제거하도록 편집되었습니다.
JaakkoK 2010 년

마지막 글 머리 기호로 머리에 못을 박은 것 같아요. 다른 것들은 해결할 수 있지만 마지막 부분은 JITed 코드가 지속되지 않는 주된 이유라고 생각합니다.
Sasha Chedygov

1
명시 적 바이트 코드-네이티브 컴파일러에 대한 마지막 단락은 현재 NGEN ( msdn.microsoft.com/en-us/library/6t9t5wcf(VS.71).aspx ) 과 함께 .NET에있는 것 입니다.
R. Martinho Fernandes
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.