Thursday, May 2, 2024
HomeJavaUse JMH on your Java purposes with Gradle - Java Code Geeks

Use JMH on your Java purposes with Gradle – Java Code Geeks


If you wish to benchmark you code, the Java Microbenchmark Harness is the device of alternative.
In our instance we will use the refill-rate-limiter mission

Since refill-rate-limiter makes use of Gradle we’ll use the next plugin for gradle

plugins {
...
  id "me.champeau.gradle.jmh" model "0.5.3"
...
}

We will place the Benchmark on the jmh/java/io/github/resilience4j/ratelimiter folder.

Our Benchmark ought to appear like this.

bundle io.github.resilience4j.ratelimiter;

import io.github.resilience4j.ratelimiter.inner.RefillRateLimiter;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
import org.openjdk.jmh.profile.GCProfiler;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.choices.Choices;
import org.openjdk.jmh.runner.choices.OptionsBuilder;

import java.time.Length;
import java.util.concurrent.TimeUnit;
import java.util.perform.Provider;

@State(Scope.Benchmark)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@BenchmarkMode(Mode.All)
public class RateLimiterBenchmark {

    personal static remaining int FORK_COUNT = 2;
    personal static remaining int WARMUP_COUNT = 10;
    personal static remaining int ITERATION_COUNT = 10;
    personal static remaining int THREAD_COUNT = 2;

    personal RefillRateLimiter refillRateLimiter;

    personal Provider<String> refillGuardedSupplier;

    public static void primary(String[] args) throws RunnerException {
        Choices choices = new OptionsBuilder()
                .addProfiler(GCProfiler.class)
                .construct();
        new Runner(choices).run();
    }

    @Setup
    public void setUp() {

        RefillRateLimiterConfig refillRateLimiterConfig = RefillRateLimiterConfig.customized()
                                                                                 .limitForPeriod(1)
                                                                                 .limitRefreshPeriod(Length.ofNanos(1))
                                                                                 .timeoutDuration(Length.ofSeconds(5))
                                                                                 .construct();

        refillRateLimiter = new RefillRateLimiter("refillBased", refillRateLimiterConfig);

        Provider<String> stringSupplier = () -> {
            Blackhole.consumeCPU(1);
            return "Howdy Benchmark";
        };

        refillGuardedSupplier = RateLimiter.decorateSupplier(refillRateLimiter, stringSupplier);
    }

    @Benchmark
    @Threads(worth = THREAD_COUNT)
    @Warmup(iterations = WARMUP_COUNT)
    @Fork(worth = FORK_COUNT)
    @Measurement(iterations = ITERATION_COUNT)
    public String refillPermission() {
        return refillGuardedSupplier.get();
    }

}

Let’s now examine the weather one after the other.

By utilizing Benchmark scope all of the threads used on the benchmark scope will share the identical object. We achieve this as a result of we wish to take a look at how refill-rate-limiter performs in a multithreaded state of affairs.

We wish our outcomes to be reported in microseconds, due to this fact we will use the OutputTimeUnit.

@OutputTimeUnit(TimeUnit.MICROSECONDS)

On JMH We’ve got varied benchmark modes relying on what we wish to measure.

Throughput is once we wish to measure the quantity operations per unit of time.
AverageTime once we wish to measure the typical time per operation.
SampleTime once we wish to pattern the time for every operation together with min, max time, extra than simply the typical.
SingleShotTime: once we wish to measure the time for a single operation. This may also help once we wish to establish how the operation will do on a chilly begin.

We even have the choice to measure all of the above.

These choices configured on the category degree will apply to the benchmark strategies we will add.

Let’s additionally study how the benchmark will run

We are going to specify the variety of Threads by utilizing the Threads annotation.

@Threads(worth = THREAD_COUNT)

Additionally we wish to heat up earlier than we run the precise benchmarks. This fashion our code can be initialized, on-line optimizations will happen, and our runtime will adapt to the situations earlier than we run the benchmarks.

@Warmup(iterations = WARMUP_COUNT)

Utilizing a Fork we will instruct what number of instances the benchmark will run.

@Fork(worth = FORK_COUNT)

Then we have to specify the variety of iterations we wish to measure/

@Measurement(iterations = ITERATION_COUNT)

We will begin our take a look at by simply utilizing

The outcomes can be save in a file.

...
2022-10-28T09:08:44.522+0100 [QUIET] [system.out] Benchmark result's saved to /path/refill-rate-limiter/construct/stories/jmh/outcomes.txt
..

Let’s study the outcomes.

Benchmark                                                         Mode       Cnt      Rating   Error   Models
RateLimiterBenchmark.refillPermission                            thrpt        20     13.594 ± 0.217  ops/us
RateLimiterBenchmark.refillPermission                             avgt        20      0.147 ± 0.002   us/op
RateLimiterBenchmark.refillPermission                           pattern  10754462      0.711 ± 0.025   us/op
RateLimiterBenchmark.refillPermission:refillPermission·p0.00    pattern                  ≈ 0           us/op
RateLimiterBenchmark.refillPermission:refillPermission·p0.50    pattern                0.084           us/op
RateLimiterBenchmark.refillPermission:refillPermission·p0.90    pattern                0.125           us/op
RateLimiterBenchmark.refillPermission:refillPermission·p0.95    pattern                0.125           us/op
RateLimiterBenchmark.refillPermission:refillPermission·p0.99    pattern                0.209           us/op
RateLimiterBenchmark.refillPermission:refillPermission·p0.999   pattern              139.008           us/op
RateLimiterBenchmark.refillPermission:refillPermission·p0.9999  pattern              935.936           us/op
RateLimiterBenchmark.refillPermission:refillPermission·p1.00    pattern            20709.376           us/op
RateLimiterBenchmark.refillPermission                               ss        20     14.700 ± 4.003   us/op

As we are able to see we now have the modes listed.
Depend is the variety of iterations. Other than throughput the place we measure the operations by time, the remainder is time per operation.
Throughput,Common and Single shot are easy, Pattern lists the percentiles. Error is the margin of error.

That’s it! Joyful benchmarking

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments