0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【JMH】Kotlin-DSLでJMH Gradle Pluginを用いたベンチマークを動かすまで【Kotlin】

Posted at

me.champeau.gradle.jmh 0.5.2を利用する場合、Windowsでは以下の問題が発生すると思われます。
再ビルドが通らない、ベンチマークを中断してもプロセスが死なないなどの問題が発生する場合gradle jmh --no-daemonとして実行して下さい。

【JMH】JMH Gradle PluginはWindows 10で正常に動作しない【Gradle】 - Qiita


JMH Gradle Pluginme.champeau.gradle.jmh)を用いてJMHベンチマークを動かすサンプルを紹介します。
プロジェクト全体は以下のリポジトリに上げてあります。

プロジェクトの初期化

プロジェクトは、Intellij IDEAを用いて以下のように初期化しました。

1. Kotlin DSL build scriptKotlin/JVMにチェックを付け、それ以外は外す
image.png
2. NameGroupIdを適当に設定する
image.png
以下は初期化直後のbuild.gradle.ktsです。

build.gradle.kts(変更前)
plugins {
    kotlin("jvm") version "1.4.10"
}

group = "com.wrongwrong"
version = "1.0-SNAPSHOT"

repositories {
    mavenCentral()
}

dependencies {
    implementation(kotlin("stdlib"))
}

build.gradle.ktsへの追記

プラグインとライブラリをそれぞれ追加します。

plugins {
    kotlin("jvm") version "1.4.10"
+   id("me.champeau.gradle.jmh") version "0.5.2"
}

group = "com.wrongwrong"
version = "1.0-SNAPSHOT"

repositories {
    mavenCentral()
}

dependencies {
    implementation(kotlin("stdlib"))
+   implementation(group = "org.openjdk.jmh", name = "jmh-core", version = "1.25.2")
}

src/jmhにgroupIdに合わせたパッケージを用意する

プラグインのREADMEに記載されている通り、JMH Gradle Pluginではsrc/jmh配下にベンチマークが有ることを想定しています。
また、groupIdに合わせたパッケージでなければベンチマークが正常に機能しません

よって、今回はgroup = "com.wrongwrong"としているため、以下のようなディレクトリ構成をする必要が有ります1
image.png

ここまで設定をやった上でベンチマークプログラムを作れば、gradle jmhで実行できます。

ベンチマークの追加と実行

簡単なベンチマークとして、ランダムに生成した2つのBigDecimalを足し合わせるベンチマークを行ってみます。
前節で説明した通り、パッケージはcom.wrongwrongとして配置します。

package com.wrongwrong

import org.openjdk.jmh.annotations.Benchmark
import org.openjdk.jmh.annotations.Scope
import org.openjdk.jmh.annotations.State
import java.math.BigDecimal
import java.util.concurrent.ThreadLocalRandom

// JMHのベンチマーク関連の内容は`open class`として定義する必要が有る
open class SampleBenchmark {
    @State(Scope.Thread)
    open class Input {
        val a: BigDecimal = ThreadLocalRandom.current().nextDouble(MAX_VALUE).toBigDecimal()
        val b: BigDecimal = ThreadLocalRandom.current().nextDouble(MAX_VALUE).toBigDecimal()

        companion object {
            private const val MAX_VALUE = 10000.0
        }
    }

    @Benchmark
    fun measureAdd(input: Input): BigDecimal = input.a + input.b
}

実行結果

gradle jmh --no-daemonとして実行した場合の実行結果は以下のようになります(個人情報が絡む部分は...で省略しています)。

>gradle jmh --no-daemon

> Task :jmhRunBytecodeGenerator

...

# Warmup Iteration   1: UTING [5s]
> Task :jmh
# JMH version: 1.25
# VM version: JDK 1.8.0_241, Java HotSpot(TM) 64-Bit Server VM, 25.241-b07
# VM invoker: ...
# VM options: <none>
# Warmup: 5 iterations, 10 s each
# Measurement: 5 iterations, 10 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: com.wrongwrong.SampleBenchmark.measureAdd

# Run progress: 0.00% complete, ETA 00:08:20
# Fork: 1 of 5

123535010.934 ops/s
# Warmup Iteration   2: 123979727.401 ops/s
# Warmup Iteration   3: 134043974.533 ops/s
# Warmup Iteration   4: 132468842.044 ops/s
# Warmup Iteration   5: 133974102.654 ops/s
Iteration   1: 132268760.988 ops/s]
Iteration   2: 134172199.789 ops/s5s]
Iteration   3: 132371282.057 ops/s15s]
Iteration   4: 134146688.977 ops/s25s]
Iteration   5: 132281181.244 ops/s35s]

> Task :jmh

# Run progress: 20.00% complete, ETA 00:06:41
# Fork: 2 of 5

# Warmup Iteration   1: 123418709.334 ops/s
# Warmup Iteration   2: 123974249.446 ops/s
# Warmup Iteration   3: 133771169.311 ops/s
# Warmup Iteration   4: 132314587.092 ops/s
# Warmup Iteration   5: 133683533.888 ops/s
Iteration   1: 132386673.995 ops/s35s]
Iteration   2: 133889633.018 ops/s45s]
Iteration   3: 132351518.216 ops/s55s]
Iteration   4: 133984395.968 ops/s5s]
Iteration   5: 132359193.064 ops/s15s]

> Task :jmh

# Run progress: 40.00% complete, ETA 00:05:00
# Fork: 3 of 5

# Warmup Iteration   1: 121795245.919 ops/s
# Warmup Iteration   2: 122968957.404 ops/s
# Warmup Iteration   3: 120593363.112 ops/s
# Warmup Iteration   4: 119424298.673 ops/s
# Warmup Iteration   5: 120837849.959 ops/s
Iteration   1: 119527380.883 ops/s16s]
Iteration   2: 120882687.677 ops/s26s]
Iteration   3: 119529815.116 ops/s36s]
Iteration   4: 121002476.444 ops/s46s]
Iteration   5: 119398499.673 ops/s56s]

> Task :jmh

# Run progress: 60.00% complete, ETA 00:03:20
# Fork: 4 of 5

# Warmup Iteration   1: 123466577.825 ops/s
# Warmup Iteration   2: 123937997.676 ops/s
# Warmup Iteration   3: 134091612.535 ops/s
# Warmup Iteration   4: 132087687.539 ops/s
# Warmup Iteration   5: 134119188.708 ops/s
Iteration   1: 132480152.938 ops/s56s]
Iteration   2: 133977021.297 ops/s6s]
Iteration   3: 132406987.113 ops/s16s]
Iteration   4: 134015243.441 ops/s26s]
Iteration   5: 132330706.552 ops/s36s]

> Task :jmh

# Run progress: 80.00% complete, ETA 00:01:40
# Fork: 5 of 5

# Warmup Iteration   1: 123306007.683 ops/s
# Warmup Iteration   2: 123730067.037 ops/s
# Warmup Iteration   3: 134053833.907 ops/s
# Warmup Iteration   4: 132625906.692 ops/s
# Warmup Iteration   5: 133897507.424 ops/s
Iteration   1: 132634681.882 ops/s36s]
Iteration   2: 134281816.570 ops/s46s]
Iteration   3: 132618358.352 ops/s56s]
Iteration   4: 134060049.422 ops/s6s]
Iteration   5: 132324371.611 ops/s16s]

> Task :jmh


Result "com.wrongwrong.SampleBenchmark.measureAdd":
  130467271.051 ±(99.9%) 4022370.483 ops/s [Average]
  (min, avg, max) = (119398499.673, 130467271.051, 134281816.570), stdev = 5369749.514
  CI (99.9%): [126444900.569, 134489641.534] (assumes normal distribution)


# Run complete. Total time: 00:08:21

REMEMBER: The numbers below are just data. To gain reusable insights, you need to follow up on
why the numbers are the way they are. Use profilers (see -prof, -lprof), design factorial
experiments, perform baseline and negative tests that provide experimental control, make sure
the benchmarking environment is safe on JVM/OS/HW level, ask for reviews from the domain experts.
Do not assume the numbers tell you what you want them to tell.

Benchmark                    Mode  Cnt          Score         Error  Units
SampleBenchmark.measureAdd  thrpt   25  130467271.051 ± 4022370.483  ops/s

Benchmark result is saved to ...
  1. 設定等を弄ればこの限りではないと思いますが、今回は簡単のため触れません。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?