Skip to content

Instantly share code, notes, and snippets.

@Palmr
Created July 28, 2024 22:13
Show Gist options
  • Save Palmr/e6ad0d1e91ad2b282a802d439633917f to your computer and use it in GitHub Desktop.
Save Palmr/e6ad0d1e91ad2b282a802d439633917f to your computer and use it in GitHub Desktop.
package uk.co.palmr.benchmarks;
import net.openhft.affinity.Affinity;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.profile.AsyncProfiler;
import org.openjdk.jmh.profile.GCProfiler;
import org.openjdk.jmh.results.format.ResultFormatType;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import java.lang.foreign.*;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.VarHandle;
import java.time.Instant;
import java.util.BitSet;
import java.util.concurrent.TimeUnit;
import static java.lang.foreign.ValueLayout.*;
@BenchmarkMode(Mode.SampleTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 1, time = 1)
@Measurement(iterations = 1, time = 60)
@State(Scope.Benchmark)
public class GetTimeBenchmark {
private static final SymbolLookup STD_LIB = Linker.nativeLinker().defaultLookup();
private static final MethodHandle GETTIMEOFDAY = Linker.nativeLinker().downcallHandle(
STD_LIB.find("gettimeofday").orElseThrow(),
FunctionDescriptor.of(JAVA_INT, ADDRESS, JAVA_INT));
private static final MemoryLayout TIMEVAL = MemoryLayout.structLayout(
JAVA_LONG.withName("tv_sec"),
JAVA_INT.withName("tv_usec")
).withName("timeval");
private static final VarHandle TV_SEC = TIMEVAL.varHandle(PathElement.groupElement("tv_sec"));
private static final VarHandle TV_USEC = TIMEVAL.varHandle(PathElement.groupElement("tv_usec"));
private static final MemorySegment TV = Arena.ofConfined().allocate(TIMEVAL);
private static final int CLOCK_MONOTONIC = 1;
private static final MethodHandle CLOCK_GETTIME = Linker.nativeLinker().downcallHandle(
STD_LIB.find("clock_gettime").orElseThrow(),
FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS));
private static final MemoryLayout TIMESPEC = MemoryLayout.structLayout(
JAVA_LONG.withName("tv_sec"),
JAVA_LONG.withName("tv_nsec")
).withName("timespec");
private static final VarHandle TIMESPEC_TVSEC = TIMESPEC.varHandle(PathElement.groupElement("tv_sec"));
private static final VarHandle TIMESPEC_TVNSEC = TIMESPEC.varHandle(PathElement.groupElement("tv_nsec"));
private static final MemorySegment TP = Arena.ofConfined().allocate(TIMESPEC);
@Setup
public void setup()
{
final var affinity = new BitSet(31);
affinity.set(14);
Affinity.setAffinity(affinity);
}
@Benchmark
public long systemCurrentTimeMillis() {
return System.currentTimeMillis();
}
@Benchmark
public long systemNanoTime() {
return System.nanoTime();
}
@Benchmark
public long instantNowToEpochMilli() {
return Instant.now().toEpochMilli();
}
@Benchmark
public long instantNowNanos() {
final var now = Instant.now();
final var epochSecond = now.getEpochSecond();
return epochSecond * 1_000_000_000 + now.getNano();
}
@Benchmark
public long instantNowMicros() {
final var now = Instant.now();
return now.getEpochSecond() * 1_000_000 + now.getNano() / 1_000;
}
@Benchmark
public long ffiLinuxGetTimeOfDay() throws Throwable {
GETTIMEOFDAY.invoke(TV, 0);
return (long) TV_SEC.get(TV) * 1_000_000 + (int) TV_USEC.get(TV);
}
@Benchmark
public long ffiLinuxClockGetTime() throws Throwable {
CLOCK_GETTIME.invoke(CLOCK_MONOTONIC, TP);
return (long) TIMESPEC_TVSEC.get(TP) * 1_000_000_000 + (long) TIMESPEC_TVNSEC.get(TP);
}
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(GetTimeBenchmark.class.getSimpleName())
.jvmArgs("--enable-preview", "--enable-native-access=ALL-UNNAMED")
.addProfiler(GCProfiler.class)
.addProfiler(AsyncProfiler.class, "libPath=/home/nick/Downloads/async-profiler-3.0-linux-x64/lib/libasyncProfiler.so;dir=out;output=flamegraph")
.addProfiler("perf")
// .addProfiler("stack")
.shouldFailOnError(true)
.result("out/results.json")
.resultFormat(ResultFormatType.JSON)
.build();
new Runner(opt).run();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment