Created
February 20, 2023 21:32
-
-
Save carl-mastrangelo/7a5e96f14423e70fdddcb1f4b50a8cc0 to your computer and use it in GitHub Desktop.
Sleep Executors
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Benchmark (executor) (sleepMillis) (sleeps) Mode Cnt Score Error Units | |
SleeperBenchmark.Bench.run CACHED 1 1 ss 30 1.180 ± 0.028 ms/op | |
SleeperBenchmark.Bench.run CACHED 1 8 ss 30 1.227 ± 0.044 ms/op | |
SleeperBenchmark.Bench.run CACHED 1 64 ss 30 1.365 ± 0.045 ms/op | |
SleeperBenchmark.Bench.run CACHED 1 512 ss 30 3.764 ± 0.476 ms/op | |
SleeperBenchmark.Bench.run CACHED 1 4096 ss 30 13.375 ± 0.996 ms/op | |
SleeperBenchmark.Bench.run FIXED 1 1 ss 30 1.234 ± 0.035 ms/op | |
SleeperBenchmark.Bench.run FIXED 1 8 ss 30 1.362 ± 0.084 ms/op | |
SleeperBenchmark.Bench.run FIXED 1 64 ss 30 9.433 ± 0.409 ms/op | |
SleeperBenchmark.Bench.run FIXED 1 512 ss 30 72.901 ± 0.540 ms/op | |
SleeperBenchmark.Bench.run FIXED 1 4096 ss 30 588.834 ± 2.089 ms/op | |
SleeperBenchmark.Bench.run FJP 1 1 ss 30 1.313 ± 0.178 ms/op | |
SleeperBenchmark.Bench.run FJP 1 8 ss 30 1.526 ± 0.099 ms/op | |
SleeperBenchmark.Bench.run FJP 1 64 ss 30 1.871 ± 0.258 ms/op | |
SleeperBenchmark.Bench.run FJP 1 512 ss 30 7.576 ± 2.723 ms/op | |
SleeperBenchmark.Bench.run FJP 1 4096 ss 30 42.071 ± 32.532 ms/op | |
SleeperBenchmark.Bench.run VIRTUAL 1 1 ss 30 1.544 ± 0.114 ms/op | |
SleeperBenchmark.Bench.run VIRTUAL 1 8 ss 30 1.407 ± 0.051 ms/op | |
SleeperBenchmark.Bench.run VIRTUAL 1 64 ss 30 1.574 ± 0.241 ms/op | |
SleeperBenchmark.Bench.run VIRTUAL 1 512 ss 30 2.586 ± 0.410 ms/op | |
SleeperBenchmark.Bench.run VIRTUAL 1 4096 ss 30 7.318 ± 1.268 ms/op | |
SleeperBenchmark.Bench.run DIRECT 1 1 ss 30 1.151 ± 0.021 ms/op | |
SleeperBenchmark.Bench.run DIRECT 1 8 ss 30 9.176 ± 0.157 ms/op | |
SleeperBenchmark.Bench.run DIRECT 1 64 ss 30 73.271 ± 1.302 ms/op | |
SleeperBenchmark.Bench.run DIRECT 1 512 ss 30 578.302 ± 4.631 ms/op | |
SleeperBenchmark.Bench.run DIRECT 1 4096 ss 30 4645.557 ± 9.266 ms/op | |
*/ | |
package bench; | |
import java.time.Duration; | |
import java.util.ArrayList; | |
import java.util.List; | |
import java.util.concurrent.AbstractExecutorService; | |
import java.util.concurrent.Callable; | |
import java.util.concurrent.ExecutorService; | |
import java.util.concurrent.Executors; | |
import java.util.concurrent.ForkJoinPool; | |
import java.util.concurrent.Future; | |
import java.util.concurrent.TimeUnit; | |
import java.util.function.Supplier; | |
import org.junit.Test; | |
import org.junit.runner.RunWith; | |
import org.junit.runners.JUnit4; | |
import org.openjdk.jmh.annotations.Benchmark; | |
import org.openjdk.jmh.annotations.BenchmarkMode; | |
import org.openjdk.jmh.annotations.Level; | |
import org.openjdk.jmh.annotations.Mode; | |
import org.openjdk.jmh.annotations.OutputTimeUnit; | |
import org.openjdk.jmh.annotations.Param; | |
import org.openjdk.jmh.annotations.Scope; | |
import org.openjdk.jmh.annotations.Setup; | |
import org.openjdk.jmh.annotations.State; | |
import org.openjdk.jmh.annotations.TearDown; | |
import org.openjdk.jmh.runner.Runner; | |
import org.openjdk.jmh.runner.options.Options; | |
import org.openjdk.jmh.runner.options.OptionsBuilder; | |
import org.openjdk.jmh.runner.options.TimeValue; | |
@RunWith(JUnit4.class) | |
public class SleeperBenchmark { | |
@Test | |
public void markHolderBenchmark() throws Exception { | |
Options options = new OptionsBuilder() | |
.include(Bench.class.getCanonicalName()) | |
.measurementIterations(30) | |
.warmupIterations(10) | |
.forks(1) | |
.warmupTime(TimeValue.seconds(20)) | |
.measurementTime(TimeValue.seconds(20)) | |
.shouldFailOnError(true) | |
// This is necessary to run in the IDE, otherwise it would inherit the VM args. | |
.jvmArgs("-da", "--enable-preview") | |
.build(); | |
new Runner(options).run(); | |
} | |
@State(Scope.Benchmark) | |
public static class Bench { | |
private static final class Sleeper implements Callable<Long>, ForkJoinPool.ManagedBlocker { | |
private final long nanosToSleep; | |
Sleeper(long nanosToSleep) { | |
this.nanosToSleep = nanosToSleep; | |
} | |
@Override | |
public Long call() { | |
long now = System.nanoTime(); | |
try { | |
ForkJoinPool.managedBlock(this); | |
} catch (InterruptedException e) { | |
Thread.currentThread().interrupt(); | |
throw new RuntimeException(e); | |
} | |
return System.nanoTime() - now; | |
} | |
@Override | |
public boolean block() throws InterruptedException { | |
TimeUnit.NANOSECONDS.sleep(nanosToSleep); | |
return true; | |
} | |
@Override | |
public boolean isReleasable() { | |
return false; | |
} | |
} | |
private ExecutorService exec; | |
@Param({"1"}) | |
public int sleepMillis; | |
@Param({"1", "8", "64", "512", "4096"}) | |
public int sleeps; | |
@Param | |
public ExecutorSupplier executor; | |
public enum ExecutorSupplier implements Supplier<ExecutorService> { | |
CACHED { | |
@Override | |
public ExecutorService get() { | |
return Executors.newCachedThreadPool(); | |
} | |
}, | |
FIXED { | |
@Override | |
public ExecutorService get() { | |
return Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); | |
} | |
}, | |
FJP { | |
@Override | |
public ExecutorService get() { | |
return new ForkJoinPool(); | |
} | |
}, | |
VIRTUAL { | |
@Override | |
public ExecutorService get() { | |
return Executors.newVirtualThreadPerTaskExecutor(); | |
} | |
}, | |
DIRECT { | |
@Override | |
public ExecutorService get() { | |
return new AbstractExecutorService() { | |
@Override | |
public void execute(Runnable command) { | |
command.run(); | |
} | |
@Override | |
public void shutdown() {} | |
@Override | |
public List<Runnable> shutdownNow() { | |
return List.of(); | |
} | |
@Override | |
public boolean isShutdown() { | |
return false; | |
} | |
@Override | |
public boolean isTerminated() { | |
return false; | |
} | |
@Override | |
public boolean awaitTermination(long timeout, TimeUnit unit) { | |
return true; | |
} | |
}; | |
} | |
} | |
; | |
} | |
private final List<Callable<Long>> sleepers = new ArrayList<>(); | |
@Setup(Level.Trial) | |
public void setUp() { | |
exec = executor.get(); | |
for (int i = 0; i < sleeps; i++) { | |
sleepers.add(new Sleeper(Duration.ofMillis(sleepMillis).toNanos())); | |
} | |
} | |
@TearDown | |
public void tearDown() { | |
exec.close(); | |
} | |
@Benchmark | |
@BenchmarkMode(Mode.SingleShotTime) | |
@OutputTimeUnit(TimeUnit.MILLISECONDS) | |
public long run() throws InterruptedException { | |
return exec.invokeAll(sleepers).stream().map(Future::resultNow).reduce(0L, Long::sum); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment