19
19
20
20
import java .time .Duration ;
21
21
import java .util .concurrent .TimeUnit ;
22
- import java .util .concurrent .locks .LockSupport ;
23
22
import java .util .function .Supplier ;
24
23
25
24
@ State (Scope .Benchmark )
26
25
@ OutputTimeUnit (TimeUnit .MICROSECONDS )
27
- @ BenchmarkMode (Mode .Throughput )
26
+ @ BenchmarkMode (Mode .AverageTime )
28
27
public class RateLimiterBenchmark {
29
28
30
29
public static final int FORK_COUNT = 2 ;
@@ -64,64 +63,104 @@ public void setUp() {
64
63
@ Warmup (iterations = WARMUP_COUNT )
65
64
@ Fork (value = FORK_COUNT )
66
65
@ 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 );
71
69
}
72
70
73
71
@ Benchmark
74
72
@ Threads (value = THREAD_COUNT )
75
73
@ Warmup (iterations = WARMUP_COUNT )
76
74
@ Fork (value = FORK_COUNT )
77
75
@ 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 );
82
79
}
83
80
84
81
@ Benchmark
85
82
@ Threads (value = THREAD_COUNT )
86
83
@ Warmup (iterations = WARMUP_COUNT )
87
84
@ Fork (value = FORK_COUNT )
88
85
@ 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 );
108
89
}
109
90
110
91
@ Benchmark
111
92
@ Threads (value = THREAD_COUNT )
112
93
@ Warmup (iterations = WARMUP_COUNT )
113
94
@ Fork (value = FORK_COUNT )
114
95
@ 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 );
117
99
}
118
100
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
+ // }
127
166
}
0 commit comments