TAKEO

TAKEO

Java JITコンパイルを体感しよう

とりあえず体感してみよう

JITDemo.javaを使用してJITを無効にした時と有効にした時の処理時間を見てみます。

JITDemo.java
Copied!!
public class JITDemo {

    public static void main(String[] args) {
        // ウォームアップ
        System.out.println("Warming up...");
        for (int i = 0; i < 10000; i++) {
            performCalculation();
        }

        // 実行時間の計測
        System.out.println("Running test...");
        long startTime = System.nanoTime();

        for (int i = 0; i < 1000000; i++) {
            performCalculation();
        }

        long endTime = System.nanoTime();
        long duration = (endTime - startTime) / 1_000_000; // ミリ秒に変換
        System.out.println("Execution time: " + duration + " ms");
    }

    private static double performCalculation() {
        double result = 0.0;
        for (int i = 1; i < 1000; i++) {
            result += Math.sqrt(i);
        }
        return result;
    }
}
  1. コンパイル

    Copied!!
    $ javac JITDemo.java
    
    • JITDemo.classというファイルが生成されます
  2. JITを無効にして実行する場合(インタプリターモード)

    Copied!!
    $ java -Xint JITDemo
    Warming up...
    Running test...
    Execution time: 7688 ms
    
    • -Xintオプションを使用します
  3. JITを有効にして実行する場合(通常モード)

    Copied!!
    $ java JITDemo
    Warming up...
    Running test...
    Execution time: 329 ms
    

処理時間の比較

  • JITが無効な時:7688 ms
  • JITが有効な時:329 ms

(7688 - 329) / 7688 * 100 ≒ 95.7(%)も実行時間が短くなっていますね!

所感とまとめ

実は私、今回初めて-Xintオプションを使用しました。JITの効果を体感しようと思っていたら、実は普段からJITの恩恵を授かっていたわけですね笑

以降はJITについて調べたことをまとめています。参考にしてください。

JITとは

JIT(Just-in-Time)コンパイルとは、Javaなどの一部のプログラミング言語における実行時の最適化技術の一つです。JITは、プログラムを実行するタイミングでコードを機械語にコンパイルすることで、実行パフォーマンスを向上させる役割を果たします。

JITコンパイルの仕組み

通常、Javaなどのプログラムは次のように実行されます。

  1. ソースコードからバイトコードへのコンパイル(共通)

    Javaコードはまず、Javaコンパイラ(javac)によってバイトコードに変換されます。このバイトコードは中間表現で、Java仮想マシン(JVM)上で実行されるように設計されています。

    Copied!!
    ソースコード ▶ バイトコード(中間表現)
    
  2. JVMによるインタプリタ実行の場合

    JVMは、バイトコードを1命令ずつ解釈して実行するインタプリタとして機能しますが、この方法はCPUにとっては効率が悪く、処理が遅くなりがちです。

    Copied!!
    ソースコード ▶ バイトコード(中間表現) ▶ 実行
    
  3. JITコンパイルを使用して実行する場合

    JITコンパイラは、プログラムの実行時に頻繁に使用される部分のバイトコードを機械語に変換します。この変換された機械語は、直接CPUで実行されるため、インタプリタ実行よりもはるかに高速に動作します。JITは特定のメソッドやループのように、繰り返し実行される「ホットスポット」に対してのみ最適化を行うため、効率的な動作が可能です。

    Copied!!
    ソースコード ▶ バイトコード(中間表現) ▶ 機械語(JITコンパイラ) ▶ 実行
    

筆者の実行環境

Copied!!
$ java -version
openjdk version "11.0.24" 2024-07-16
OpenJDK Runtime Environment (build 11.0.24+8-post-Ubuntu-1ubuntu322.04)
OpenJDK 64-Bit Server VM (build 11.0.24+8-post-Ubuntu-1ubuntu322.04, mixed mode, sharing)
Copied!!
$ cat /etc/os-release
PRETTY_NAME="Ubuntu 22.04.5 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.5 LTS (Jammy Jellyfish)"
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=jammy