Java java지도 시간 Graal 살펴보기: Java용 차세대 JIT 컴파일

Graal 살펴보기: Java용 차세대 JIT 컴파일

Aug 31, 2024 pm 04:36 PM

Graal 컴파일러는 동적 Just-In Time(JIT) 컴파일 기술에서 획기적인 발전을 이루었습니다. Java의 인상적인 성능 뒤에 중요한 요소로 알려진 Java Virtual Machine(JVM) 아키텍처 내 JIT 컴파일의 역할과 기능은 복잡하고 다소 불투명한 특성으로 인해 종종 많은 실무자를 당혹스럽게 만듭니다.

JIT 컴파일러란 무엇입니까?

javac 명령을 실행하거나 IDE를 사용하면 Java 프로그램이 Java 소스 코드에서 JVM 바이트 코드로 변환됩니다. 이
프로세스는 원래 소스 코드보다 훨씬 간단하고 컴팩트한 형식인 Java 프로그램의 바이너리 표현을 생성합니다.

그러나 컴퓨터나 서버에 있는 기존 프로세서는 JVM 바이트코드를 직접 실행할 수 없습니다. 이를 위해서는 JVM이 바이트코드를 해석해야 합니다.

Exploring Graal: Next-Generation JIT Compilation for Java

그림 1 – JIT(Just-In-Time) 컴파일러 작동 방식

통역사는 종종 실제 프로세서에서 실행되는 네이티브 코드에 비해 성능이 저하될 수 있으며, 이는 JVM이 런타임에 다른 컴파일러인 JIT 컴파일러를 호출하도록 동기를 부여합니다. JIT 컴파일러는 바이트코드를 프로세서가 직접 실행할 수 있는 기계어 코드로 변환합니다. 이 정교한 컴파일러는 다양한 고급 최적화를 실행하여 고품질 기계어 코드를 생성합니다.

이 바이트코드는 중간 계층 역할을 하여 Java 애플리케이션이 다양한 프로세서 아키텍처를 갖춘 다양한 운영 체제에서 실행될 수 있도록 합니다. JVM 자체는 이 바이트코드 명령어를 명령어별로 해석하는 소프트웨어 프로그램입니다.

Graal JIT 컴파일러 - Java로 작성되었습니다.

JVM의 OpenJDK 구현에는 클라이언트 컴파일러(C1)와 서버 컴파일러(C2 또는 Opto)라는 두 가지 기존 JIT 컴파일러가 포함되어 있습니다. 클라이언트 컴파일러는 더 빠른 작업과 덜 최적화된 코드 출력에 최적화되어 있어 확장된 JIT 컴파일 일시 중지로 인해 사용자 경험이 중단될 수 있는 데스크톱 애플리케이션에 이상적입니다. 반대로, 서버 컴파일러는 고도로 최적화된 코드를 생성하는 데 더 많은 시간을 할애하도록 설계되어 장기 실행 서버 애플리케이션에 적합합니다.

'계층 컴파일'을 통해 두 컴파일러를 동시에 사용할 수 있습니다. 처음에는 코드가 C1을 통해 컴파일되고, 실행 빈도가 추가 컴파일 시간을 정당화하는 경우 C2가 이어집니다.

C++로 개발된 C2는 고성능 특성에도 불구하고 본질적인 단점이 있습니다. C++는 안전하지 않은 언어입니다. 따라서 C2 모듈의 오류로 인해 전체 VM이 충돌할 수 있습니다. 상속된 C++ 코드의 복잡성과 견고성으로 인해 유지 관리 및 확장성이 중요한 과제가 되었습니다.

Graal의 고유한 이 JIT 컴파일러는 Java로 개발되었습니다. 컴파일러의 주요 요구 사항은 JVM 바이트코드를 받아들이고 기계어 코드를 출력하는 것입니다. 이는 C나 C++와 같은 시스템 수준 언어가 필요하지 않은 높은 수준의 작업입니다.

Java로 작성된 Graal은 다음과 같은 몇 가지 이점을 제공합니다.

  • 향상된 안전성: Java의 가비지 수집 및 관리형 메모리 접근 방식은 JIT 컴파일러 자체의 메모리 관련 충돌 위험을 제거합니다.

  • 간편한 유지 관리 및 확장: Java 코드베이스는 개발자가 JIT 컴파일러에 기여하고 기능을 확장하는 데 더 쉽게 접근할 수 있습니다.

  • 이식성: Java의 플랫폼 독립성은 Graal JIT 컴파일러가 Java Virtual Machine이 있는 모든 플랫폼에서 작동할 수 있다는 의미입니다.

JVM 컴파일러 인터페이스(JVMCI)

JVMCI(JVM 컴파일러 인터페이스)는 JVM(JEP 243: https://openjdk.org/jeps/243)의 혁신적인 기능이자 새로운 인터페이스입니다.
Java 주석 처리 API와 마찬가지로 JVMCI는 사용자 정의 Java JIT 컴파일러의 통합도 허용합니다.

JVMCI 인터페이스는 바이트에서 바이트[]까지의 순수 기능으로 구성됩니다.

interface JVMCICompiler {

  byte[] compileMethod(byte[] bytecode);
}

실제 시나리오의 복잡성을 완전히 포착하지는 못합니다.

실제 응용 프로그램에서는 코드가 어떻게 작동하는지 더 잘 이해하기 위해 로컬 변수 수, 스택 크기, 인터프리터의 프로파일링에서 수집한 데이터와 같은 추가 정보가 필요한 경우가 많습니다. 따라서 인터페이스는 더 복잡한 입력을 사용합니다. 바이트코드 대신 CompilationRequest를 허용합니다.

public interface JVMCICompiler {

  int INVOCATION_ENTRY_BCI = -1;

  CompilationRequestResult compileMethod(CompilationRequest request);
}

JVMCICompiler.java

CompilationRequest는 어떤 JavaMethod가 컴파일용인지, 잠재적으로 컴파일러에 필요한 훨씬 더 많은 데이터와 같은 보다 포괄적인 정보를 캡슐화합니다.

CompilationRequest.java

This approach has the benefit of providing all necessary details to the custom JIT-compiler in a more organized and contextual manner. To create a new JIT-compiler for the JVM, one must implement the JVMCICompiler interface.

Ideal Graph

An aspect where Graal truly shines in terms of performing sophisticated code optimization is in its use of a unique data structure: the program-dependence-graph, or colloquially, an "Ideal Graph".

The program-dependence-graph is a directed graph that presents a visual representation of the dependencies between individual operations, essentially laying out the matrix of dependencies between different parts of your Java code.

Let's illustrate this concept with a simple example of adding two local variables, x and y. The program-dependence-graph for this operation in Graal's context would involve three nodes and two edges:

  • Nodes:

    • Load(x) and Load(y): These nodes represent the operations of loading the values of variables x and y from memory into registers within the processor.
    • Add: This node embodies the operation of adding the values loaded from x and y.
  • Edges:

    • Two edges would be drawn from the Load(x) and Load(y) nodes to the Add node. These directional paths convey the data flow. They signify that the values loaded from x and y are the inputs to the addition operation.
      +--------->+--------->+
      | Load(x)  | Load(y)  |
      +--------->+--------->+
                 |
                 v
              +-----+
              | Add |
              +-----+

In this illustration, the arrows represent the data flow between the nodes. The Load(x) and Load(y) nodes feed their loaded values into the Add node, which performs the addition operation. This visual representation helps Graal identify potential optimizations based on the dependencies between these operations.

This graph-based architecture provides the Graal compiler with a clear visible landscape of dependencies and scheduling in the code it compiles. The program-dependence-graph not only maps the flow of data and relationships between operations but also offers a canvas for Gaal to manipulate these relationships. Each node on the graph is a clear candidate for specific optimizations, while the edges indicate where alterations would propagate changes elsewhere in the code - both aspects influence how Graal optimizes your program's performance.

Visualizing and analyzing this graph can be achieved through a tool called the IdealGraphVisualizer, or IGV. This tool is invaluable in understanding the intricacies of Graal's code optimization capabilities. It allows you to pinpoint how specific parts of your code are being analyzed, modified, and optimized, providing valuable insights for further code enhancements.

Let's consider a simple Java program that performs a complex operation in a loop:

public class Demo {
 public static void main(String[] args) {
        for (int i = 0; i < 1_000_000; i++) {
            System.err.println(complexOperation(i, i + 2));
        }
    }

    public static int complexOperation(int a, int b) {
        return ((a + b)-a) / 2;
    }
}

When compiled with Graal, the Ideal Graph for this program would look something like this(Figure 2).

Exploring Graal: Next-Generation JIT Compilation for Java

Figure 2 – Graal Graphs

Therefore, along with its method level optimizations and overall code performance improvements, this graph-based representation constitutes the key to understanding the power of the Graal compiler in optimizing your Java applications

In Conclusion

The Graal JIT compiler represents a significant leap forward in Java performance optimization. Its unique characteristic of being written in Java itself offers a compelling alternative to traditional C-based compilers. This not only enhances safety and maintainability but also paves the way for a more dynamic and adaptable JIT compilation landscape.

The introduction of the JVM Compiler Interface (JVMCI) further amplifies this potential. By allowing the development of custom JIT compilers in Java, JVMCI opens doors for further experimentation and innovation. This could lead to the creation of specialized compilers targeting specific needs or architectures, ultimately pushing the boundaries of Java performance optimization.

In essence, Graal and JVMCI represent a paradigm shift in JIT compilation within the Java ecosystem. They lay the foundation for a future where JIT compilation can be customized, extended, and continuously improved, leading to even more performant and versatile Java applications.

위 내용은 Graal 살펴보기: Java용 차세대 JIT 컴파일의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Clothoff.io

Clothoff.io

AI 옷 제거제

Video Face Swap

Video Face Swap

완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제

해시 맵은 자바에서 내부적으로 어떻게 작동합니까? 해시 맵은 자바에서 내부적으로 어떻게 작동합니까? Jul 15, 2025 am 03:10 AM

해시 맵은 Java의 해시 테이블을 통해 키 값 쌍 스토리지를 구현하며, 그 핵심은 데이터 위치를 빠르게 배치하는 데 있습니다. 1. 먼저 키의 hashcode () 메소드를 사용하여 해시 값을 생성하고 비트 작업을 통해 배열 인덱스로 변환합니다. 2. 다른 객체가 동일한 해시 값을 생성하여 충돌을 일으킬 수 있습니다. 현재 노드는 링크 된 목록의 형태로 장착됩니다. JDK8 후 링크 된 목록이 너무 길고 (기본 길이 8) 효율을 향상시키기 위해 빨간색과 검은 색 트리로 변환됩니다. 3. 사용자 정의 클래스를 키로 사용하는 경우 equals () 및 hashcode () 메소드를 다시 작성해야합니다. 4. 해시 맵은 용량을 동적으로 확장합니다. 요소 수가 용량을 초과하고 하중 계수 (기본 0.75)를 곱하면 확장 및 재사용; 5. 해시 맵은 스레드 안전이 아니며 Multithreaded에서 Concu를 사용해야합니다.

Java 선택 예제 Java 선택 예제 Jul 12, 2025 am 02:55 AM

선택 사항은 의도를 명확하게 표현하고 널 판단에 대한 코드 노이즈를 줄일 수 있습니다. 1. 옵션. ofnullable은 null 객체를 다루는 일반적인 방법입니다. 예를 들어, 맵에서 값을 가져올 때 Orelse는 기본값을 제공하는 데 사용하여 논리가 명확하고 간결합니다. 2. 체인 호출 맵을 사용하여 중첩 값을 달성하여 NPE를 안전하게 피하고 링크가 널이면 자동으로 종료되고 기본값을 반환합니다. 3. 필터는 조건부 필터링에 사용될 수 있으며, 조건이 충족되는 경우에만 후속 작업이 계속 수행됩니다. 그렇지 않으면 가벼운 비즈니스 판단에 적합한 Orelse로 직접 이동합니다. 4. 기본 유형이나 간단한 논리와 같은 선택적 사례를 과도하게 사용하는 것은 권장되지 않으므로 복잡성을 증가 시키며 일부 시나리오는 NU로 직접 돌아갑니다.

java.io.notserializableException을 수정하는 방법? java.io.notserializableException을 수정하는 방법? Jul 12, 2025 am 03:07 AM

java.io.notserializableException을 만나기위한 핵심 해결 방법은 직렬화 해야하는 모든 클래스가 직렬화 가능한 인터페이스를 구현하고 중첩 된 객체의 직렬화 지원을 확인하는지 확인하는 것입니다. 1. 메인 클래스에 상해를 추가하십시오. 2. 클래스의 해당 커스텀 필드 클래스가 세련된 세포화 가능하도록하십시오. 3. 직렬화 할 필요가없는 마크 필드에 과도를 사용하십시오. 4. 수집 또는 중첩 된 물체에서 비 시리얼 유형을 점검하십시오. 5. 인터페이스를 구현하지 않는 클래스를 확인하십시오. 6. 키 데이터 저장 또는 직렬화 가능한 중간 구조 사용과 같이 수정할 수없는 클래스의 교체 설계를 고려하십시오. 7. 수정을 고려하십시오

Java의 캐릭터 인코딩 문제를 처리하는 방법은 무엇입니까? Java의 캐릭터 인코딩 문제를 처리하는 방법은 무엇입니까? Jul 13, 2025 am 02:46 AM

Java의 문자 인코딩 문제를 처리하려면 키는 각 단계에서 사용되는 인코딩을 명확하게 지정하는 것입니다. 1. 텍스트를 읽고 쓰는 시점에 항상 인코딩을 지정하고 InputStreamReader 및 OutputStreamWriter를 사용하고 시스템 기본 인코딩에 의존하지 않도록 명시 적 문자 세트를 전달하십시오. 2. 네트워크 경계에서 문자열을 처리 할 때 양쪽 끝이 일관되도록하고 올바른 컨텐츠 유형 헤더를 설정하고 라이브러리와 인코딩을 명시 적으로 지정하십시오. 3. String.getBytes () 및 Newstring (byte [])을주의해서 사용하고 플랫폼 차이로 인한 데이터 손상을 피하기 위해 항상 Standardcharsets.utf_8을 수동으로 지정하십시오. 요컨대,

Java 소켓 프로그래밍 기초 및 예제 Java 소켓 프로그래밍 기초 및 예제 Jul 12, 2025 am 02:53 AM

Javasocket 프로그래밍은 네트워크 통신의 기초이며, 클라이언트와 서버 간의 데이터 교환은 소켓을 통해 실현됩니다. 1. Java의 소켓은 클라이언트가 사용하는 소켓 클래스와 서버에서 사용하는 서버 소켓 클래스로 나뉩니다. 2. 소켓 프로그램을 작성할 때 먼저 서버 청취 포트를 시작한 다음 클라이언트의 연결을 시작해야합니다. 3. 커뮤니케이션 프로세스에는 연결 설정, 데이터 읽기 및 쓰기 및 스트림 폐쇄가 포함됩니다. 4. 예방 조치에는 포트 충돌을 피하고 IP 주소를 올바르게 구성하고, 자원을 합리적으로 폐쇄하고, 여러 클라이언트를 지원하는 것이 포함됩니다. 이것들을 마스터하면 기본 네트워크 통신 기능을 실현할 수 있습니다.

Java의 비교기 비교기 Java의 비교기 비교기 Jul 13, 2025 am 02:31 AM

Java에서는 비교 가능성이 기본 정렬 규칙을 내부적으로 정의하는 데 사용되며 비교기는 여러 정렬 로직을 외부로 정의하는 데 사용됩니다. 1. 클래스 자체가 구현 한 인터페이스입니다. 비교 () 메소드를 다시 작성하여 자연 순서를 정의합니다. 문자열 또는 정수와 같은 고정되고 가장 일반적으로 사용되는 분류 방법이있는 클래스에 적합합니다. 2. 비교기는 외부 정의 된 기능 인터페이스이며, 동일한 클래스에 여러 정렬 방법이 필요한 상황에 적합한 Compare () 메소드를 통해 구현되며, 클래스 소스 코드를 수정할 수 없거나 정렬 로직이 종종 변경됩니다. 둘의 차이점은 비교할 수있는 분류 논리 만 정의 할 수 있으며 클래스 자체를 수정하면서 비교할 필요가 있다는 것입니다.

Java의지도를 반복하는 방법은 무엇입니까? Java의지도를 반복하는 방법은 무엇입니까? Jul 13, 2025 am 02:54 AM

Java에는지도를 가로 지르는 세 가지 일반적인 방법이 있습니다. 1. Entryset을 사용하여 키와 값을 동시에 얻으십시오. 이는 대부분의 시나리오에 적합합니다. 2. 키즈 또는 값을 사용하여 각각 키 또는 값을 가로 지르십시오. 3. 코드 구조를 단순화하려면 Java8의 foreach를 사용하십시오. Entryset은 모든 키 값 쌍이 포함 된 세트 세트를 반환하고 각 루프는 맵을 가져옵니다. 열 객체는 키와 값에 자주 액세스하기에 적합합니다. 키나 값 만 필요한 경우 각각 Keyset () 또는 values ()를 호출하거나 키를 가로 질러 Map.Get (키)를 통해 값을 얻을 수 있습니다. Java 8은 foreach ((키, 값)-& gt를 사용할 수 있습니다

Java의 '정적'키워드는 무엇입니까? Java의 '정적'키워드는 무엇입니까? Jul 13, 2025 am 02:51 AM

injava, thestatickeywordmeansamembeLongstotheclassitself, nottoinstances.StaticvariablesAresharedAcrossAllInstances 및 OutObjectCreation, 유용한 ForgloBalTrackingorConstants.StaticMethodsOperateateAteAteClassEvel, canceCcessnon-StaticMbers, statice

See all articles