Skip to content

Commit ceb75fe

Browse files
committed
Issue ReactiveX#12 state calculation benchmark shows that most time is spending in System.nanoTime
1 parent 7fb310c commit ceb75fe

File tree

4 files changed

+84
-46
lines changed

4 files changed

+84
-46
lines changed

src/jmh/java/javaslang/circuitbreaker/RateLimiterBenchmark.java

Lines changed: 78 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,11 @@
1919

2020
import java.time.Duration;
2121
import java.util.concurrent.TimeUnit;
22-
import java.util.concurrent.locks.LockSupport;
2322
import java.util.function.Supplier;
2423

2524
@State(Scope.Benchmark)
2625
@OutputTimeUnit(TimeUnit.MICROSECONDS)
27-
@BenchmarkMode(Mode.Throughput)
26+
@BenchmarkMode(Mode.AverageTime)
2827
public class RateLimiterBenchmark {
2928

3029
public static final int FORK_COUNT = 2;
@@ -64,64 +63,104 @@ public void setUp() {
6463
@Warmup(iterations = WARMUP_COUNT)
6564
@Fork(value = FORK_COUNT)
6665
@Measurement(iterations = ITERATION_COUNT)
67-
public void mutex(Blackhole bh) {
68-
synchronized (mutex) {
69-
state = atomicRateLimiter.calculateNextState(Duration.ZERO.toNanos(), state);
70-
}
66+
public void calculateNextState(Blackhole bh) {
67+
AtomicRateLimiter.State next = atomicRateLimiter.calculateNextState(Duration.ZERO.toNanos(), this.state);
68+
bh.consume(next);
7169
}
7270

7371
@Benchmark
7472
@Threads(value = THREAD_COUNT)
7573
@Warmup(iterations = WARMUP_COUNT)
7674
@Fork(value = FORK_COUNT)
7775
@Measurement(iterations = ITERATION_COUNT)
78-
public void atomic(Blackhole bh) {
79-
atomicRateLimiter.state.updateAndGet(state -> {
80-
return atomicRateLimiter.calculateNextState(Duration.ZERO.toNanos(), state);
81-
});
76+
public void nanosToWaitForPermission(Blackhole bh) {
77+
long next = atomicRateLimiter.nanosToWaitForPermission(1, 315L, 31L);
78+
bh.consume(next);
8279
}
8380

8481
@Benchmark
8582
@Threads(value = THREAD_COUNT)
8683
@Warmup(iterations = WARMUP_COUNT)
8784
@Fork(value = FORK_COUNT)
8885
@Measurement(iterations = ITERATION_COUNT)
89-
public void atomicBackOf(Blackhole bh) {
90-
AtomicRateLimiter.State prev;
91-
AtomicRateLimiter.State next;
92-
do {
93-
prev = atomicRateLimiter.state.get();
94-
next = atomicRateLimiter.calculateNextState(Duration.ZERO.toNanos(), prev);
95-
} while (!compareAndSet(prev, next));
96-
}
97-
98-
/*
99-
https://arxiv.org/abs/1305.5800 https://dzone.com/articles/wanna-get-faster-wait-bit
100-
*/
101-
public boolean compareAndSet(final AtomicRateLimiter.State current, final AtomicRateLimiter.State next) {
102-
if (atomicRateLimiter.state.compareAndSet(current, next)) {
103-
return true;
104-
} else {
105-
LockSupport.parkNanos(1);
106-
return false;
107-
}
86+
public void reservePermissions(Blackhole bh) {
87+
AtomicRateLimiter.State next = atomicRateLimiter.reservePermissions(0L, 31L, 1, 0L);
88+
bh.consume(next);
10889
}
10990

11091
@Benchmark
11192
@Threads(value = THREAD_COUNT)
11293
@Warmup(iterations = WARMUP_COUNT)
11394
@Fork(value = FORK_COUNT)
11495
@Measurement(iterations = ITERATION_COUNT)
115-
public String semaphoreBasedPermission() {
116-
return semaphoreGuardedSupplier.get();
96+
public void currentNanoTime(Blackhole bh) {
97+
long next = atomicRateLimiter.currentNanoTime();
98+
bh.consume(next);
11799
}
118100

119-
@Benchmark
120-
@Threads(value = THREAD_COUNT)
121-
@Warmup(iterations = WARMUP_COUNT)
122-
@Fork(value = FORK_COUNT)
123-
@Measurement(iterations = ITERATION_COUNT)
124-
public String atomicPermission() {
125-
return atomicGuardedSupplier.get();
126-
}
101+
// @Benchmark
102+
// @Threads(value = THREAD_COUNT)
103+
// @Warmup(iterations = WARMUP_COUNT)
104+
// @Fork(value = FORK_COUNT)
105+
// @Measurement(iterations = ITERATION_COUNT)
106+
// public void mutex(Blackhole bh) {
107+
// synchronized (mutex) {
108+
// state = atomicRateLimiter.calculateNextState(Duration.ZERO.toNanos(), state);
109+
// }
110+
// }
111+
//
112+
// @Benchmark
113+
// @Threads(value = THREAD_COUNT)
114+
// @Warmup(iterations = WARMUP_COUNT)
115+
// @Fork(value = FORK_COUNT)
116+
// @Measurement(iterations = ITERATION_COUNT)
117+
// public void atomic(Blackhole bh) {
118+
// atomicRateLimiter.state.updateAndGet(state -> {
119+
// return atomicRateLimiter.calculateNextState(Duration.ZERO.toNanos(), state);
120+
// });
121+
// }
122+
//
123+
// @Benchmark
124+
// @Threads(value = THREAD_COUNT)
125+
// @Warmup(iterations = WARMUP_COUNT)
126+
// @Fork(value = FORK_COUNT)
127+
// @Measurement(iterations = ITERATION_COUNT)
128+
// public void atomicBackOf(Blackhole bh) {
129+
// AtomicRateLimiter.State prev;
130+
// AtomicRateLimiter.State next;
131+
// do {
132+
// prev = atomicRateLimiter.state.get();
133+
// next = atomicRateLimiter.calculateNextState(Duration.ZERO.toNanos(), prev);
134+
// } while (!compareAndSet(prev, next));
135+
// }
136+
//
137+
// /*
138+
// https://arxiv.org/abs/1305.5800 https://dzone.com/articles/wanna-get-faster-wait-bit
139+
// */
140+
// public boolean compareAndSet(final AtomicRateLimiter.State current, final AtomicRateLimiter.State next) {
141+
// if (atomicRateLimiter.state.compareAndSet(current, next)) {
142+
// return true;
143+
// } else {
144+
// LockSupport.parkNanos(1);
145+
// return false;
146+
// }
147+
// }
148+
//
149+
// @Benchmark
150+
// @Threads(value = THREAD_COUNT)
151+
// @Warmup(iterations = WARMUP_COUNT)
152+
// @Fork(value = FORK_COUNT)
153+
// @Measurement(iterations = ITERATION_COUNT)
154+
// public String semaphoreBasedPermission() {
155+
// return semaphoreGuardedSupplier.get();
156+
// }
157+
//
158+
// @Benchmark
159+
// @Threads(value = THREAD_COUNT)
160+
// @Warmup(iterations = WARMUP_COUNT)
161+
// @Fork(value = FORK_COUNT)
162+
// @Measurement(iterations = ITERATION_COUNT)
163+
// public String atomicPermission() {
164+
// return atomicGuardedSupplier.get();
165+
// }
127166
}

src/jmh/java/javaslang/circuitbreaker/casWithBackOff.txt

Lines changed: 0 additions & 6 deletions
This file was deleted.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Benchmark Mode Cnt Score Error Units
2+
RateLimiterBenchmark.calculateNextState avgt 10 0.101 ± 0.008 us/op
3+
RateLimiterBenchmark.currentNanoTime avgt 10 0.077 ± 0.001 us/op
4+
RateLimiterBenchmark.nanosToWaitForPermission avgt 10 0.003 ± 0.001 us/op
5+
RateLimiterBenchmark.reservePermissions avgt 10 0.007 ± 0.001 us/op

src/main/java/javaslang/ratelimiter/internal/AtomicRateLimiter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ public long getAvailablePermissions() {
264264
/**
265265
* Created only for test purposes. Simply calls {@link System#nanoTime()}
266266
*/
267-
private long currentNanoTime() {
267+
public long currentNanoTime() {
268268
return nanoTime();
269269
}
270270
}

0 commit comments

Comments
 (0)