Skip to content

Commit

Permalink
Issue ReactiveX#12 state calculation benchmark shows that most time i…
Browse files Browse the repository at this point in the history
…s spending in System.nanoTime
  • Loading branch information
storozhukBM committed Dec 2, 2016
1 parent 576aad1 commit 08312ea
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 46 deletions.
117 changes: 78 additions & 39 deletions src/jmh/java/javaslang/circuitbreaker/RateLimiterBenchmark.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,11 @@

import java.time.Duration;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
import java.util.function.Supplier;

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

public static final int FORK_COUNT = 2;
Expand Down Expand Up @@ -64,64 +63,104 @@ public void setUp() {
@Warmup(iterations = WARMUP_COUNT)
@Fork(value = FORK_COUNT)
@Measurement(iterations = ITERATION_COUNT)
public void mutex(Blackhole bh) {
synchronized (mutex) {
state = atomicRateLimiter.calculateNextState(Duration.ZERO.toNanos(), state);
}
public void calculateNextState(Blackhole bh) {
AtomicRateLimiter.State next = atomicRateLimiter.calculateNextState(Duration.ZERO.toNanos(), this.state);
bh.consume(next);
}

@Benchmark
@Threads(value = THREAD_COUNT)
@Warmup(iterations = WARMUP_COUNT)
@Fork(value = FORK_COUNT)
@Measurement(iterations = ITERATION_COUNT)
public void atomic(Blackhole bh) {
atomicRateLimiter.state.updateAndGet(state -> {
return atomicRateLimiter.calculateNextState(Duration.ZERO.toNanos(), state);
});
public void nanosToWaitForPermission(Blackhole bh) {
long next = atomicRateLimiter.nanosToWaitForPermission(1, 315L, 31L);
bh.consume(next);
}

@Benchmark
@Threads(value = THREAD_COUNT)
@Warmup(iterations = WARMUP_COUNT)
@Fork(value = FORK_COUNT)
@Measurement(iterations = ITERATION_COUNT)
public void atomicBackOf(Blackhole bh) {
AtomicRateLimiter.State prev;
AtomicRateLimiter.State next;
do {
prev = atomicRateLimiter.state.get();
next = atomicRateLimiter.calculateNextState(Duration.ZERO.toNanos(), prev);
} while (!compareAndSet(prev, next));
}

/*
https://arxiv.org/abs/1305.5800 https://dzone.com/articles/wanna-get-faster-wait-bit
*/
public boolean compareAndSet(final AtomicRateLimiter.State current, final AtomicRateLimiter.State next) {
if (atomicRateLimiter.state.compareAndSet(current, next)) {
return true;
} else {
LockSupport.parkNanos(1);
return false;
}
public void reservePermissions(Blackhole bh) {
AtomicRateLimiter.State next = atomicRateLimiter.reservePermissions(0L, 31L, 1, 0L);
bh.consume(next);
}

@Benchmark
@Threads(value = THREAD_COUNT)
@Warmup(iterations = WARMUP_COUNT)
@Fork(value = FORK_COUNT)
@Measurement(iterations = ITERATION_COUNT)
public String semaphoreBasedPermission() {
return semaphoreGuardedSupplier.get();
public void currentNanoTime(Blackhole bh) {
long next = atomicRateLimiter.currentNanoTime();
bh.consume(next);
}

@Benchmark
@Threads(value = THREAD_COUNT)
@Warmup(iterations = WARMUP_COUNT)
@Fork(value = FORK_COUNT)
@Measurement(iterations = ITERATION_COUNT)
public String atomicPermission() {
return atomicGuardedSupplier.get();
}
// @Benchmark
// @Threads(value = THREAD_COUNT)
// @Warmup(iterations = WARMUP_COUNT)
// @Fork(value = FORK_COUNT)
// @Measurement(iterations = ITERATION_COUNT)
// public void mutex(Blackhole bh) {
// synchronized (mutex) {
// state = atomicRateLimiter.calculateNextState(Duration.ZERO.toNanos(), state);
// }
// }
//
// @Benchmark
// @Threads(value = THREAD_COUNT)
// @Warmup(iterations = WARMUP_COUNT)
// @Fork(value = FORK_COUNT)
// @Measurement(iterations = ITERATION_COUNT)
// public void atomic(Blackhole bh) {
// atomicRateLimiter.state.updateAndGet(state -> {
// return atomicRateLimiter.calculateNextState(Duration.ZERO.toNanos(), state);
// });
// }
//
// @Benchmark
// @Threads(value = THREAD_COUNT)
// @Warmup(iterations = WARMUP_COUNT)
// @Fork(value = FORK_COUNT)
// @Measurement(iterations = ITERATION_COUNT)
// public void atomicBackOf(Blackhole bh) {
// AtomicRateLimiter.State prev;
// AtomicRateLimiter.State next;
// do {
// prev = atomicRateLimiter.state.get();
// next = atomicRateLimiter.calculateNextState(Duration.ZERO.toNanos(), prev);
// } while (!compareAndSet(prev, next));
// }
//
// /*
// https://arxiv.org/abs/1305.5800 https://dzone.com/articles/wanna-get-faster-wait-bit
// */
// public boolean compareAndSet(final AtomicRateLimiter.State current, final AtomicRateLimiter.State next) {
// if (atomicRateLimiter.state.compareAndSet(current, next)) {
// return true;
// } else {
// LockSupport.parkNanos(1);
// return false;
// }
// }
//
// @Benchmark
// @Threads(value = THREAD_COUNT)
// @Warmup(iterations = WARMUP_COUNT)
// @Fork(value = FORK_COUNT)
// @Measurement(iterations = ITERATION_COUNT)
// public String semaphoreBasedPermission() {
// return semaphoreGuardedSupplier.get();
// }
//
// @Benchmark
// @Threads(value = THREAD_COUNT)
// @Warmup(iterations = WARMUP_COUNT)
// @Fork(value = FORK_COUNT)
// @Measurement(iterations = ITERATION_COUNT)
// public String atomicPermission() {
// return atomicGuardedSupplier.get();
// }
}
6 changes: 0 additions & 6 deletions src/jmh/java/javaslang/circuitbreaker/casWithBackOff.txt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Benchmark Mode Cnt Score Error Units
RateLimiterBenchmark.calculateNextState avgt 10 0.101 ± 0.008 us/op
RateLimiterBenchmark.currentNanoTime avgt 10 0.077 ± 0.001 us/op
RateLimiterBenchmark.nanosToWaitForPermission avgt 10 0.003 ± 0.001 us/op
RateLimiterBenchmark.reservePermissions avgt 10 0.007 ± 0.001 us/op
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ public long getAvailablePermissions() {
/**
* Created only for test purposes. Simply calls {@link System#nanoTime()}
*/
private long currentNanoTime() {
public long currentNanoTime() {
return nanoTime();
}
}

0 comments on commit 08312ea

Please sign in to comment.