Skip to content

Commit 15bcef0

Browse files
committed
Issue ReactiveX#12 TimeBasedRateLimiter and AtomicRateLimiter implementations + benchmarks
1 parent b2f28fd commit 15bcef0

15 files changed

+734
-152
lines changed

build.gradle

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@ buildscript {
22
repositories {
33
jcenter()
44
mavenCentral()
5+
maven {
6+
url "https://plugins.gradle.org/m2/"
7+
}
58
}
69
dependencies {
710
classpath 'org.kt3k.gradle.plugin:coveralls-gradle-plugin:2.0.1'
811
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.2'
9-
classpath 'me.champeau.gradle:jmh-gradle-plugin:0.2.0'
12+
classpath 'me.champeau.gradle:jmh-gradle-plugin:0.3.1'
1013
classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.0'
1114
classpath "org.asciidoctor:asciidoctor-gradle-plugin:1.5.3"
1215
classpath "org.ajoberstar:gradle-git:1.3.2"
@@ -50,12 +53,7 @@ repositories {
5053
}
5154

5255
jmh {
53-
benchmarkMode = 'all'
54-
jmhVersion = '1.11.2'
55-
fork = 1
56-
threads = 10
57-
iterations = 2
58-
warmupIterations = 2
56+
jmhVersion = '1.17'
5957
include=''
6058
}
6159

gradlew

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,6 @@ case "`uname`" in
4242
;;
4343
esac
4444

45-
# For Cygwin, ensure paths are in UNIX format before anything is touched.
46-
if $cygwin ; then
47-
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48-
fi
49-
5045
# Attempt to set APP_HOME
5146
# Resolve links: $0 may be a link
5247
PRG="$0"
@@ -61,9 +56,9 @@ while [ -h "$PRG" ] ; do
6156
fi
6257
done
6358
SAVED="`pwd`"
64-
cd "`dirname \"$PRG\"`/" >&-
59+
cd "`dirname \"$PRG\"`/" >/dev/null
6560
APP_HOME="`pwd -P`"
66-
cd "$SAVED" >&-
61+
cd "$SAVED" >/dev/null
6762

6863
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
6964

@@ -114,6 +109,7 @@ fi
114109
if $cygwin ; then
115110
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116111
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112+
JAVACMD=`cygpath --unix "$JAVACMD"`
117113

118114
# We build the pattern for arguments to be converted via cygpath
119115
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
Benchmark Mode Cnt Score Error Units
2+
3+
RateLimiterBenchmark.atomicPermission thrpt 10 7.274 ± 0.132 ops/us
4+
RateLimiterBenchmark.semaphoreBasedPermission thrpt 10 17.335 ± 3.441 ops/us
5+
RateLimiterBenchmark.timeBasedPermission thrpt 10 3.522 ± 0.495 ops/us
6+
7+
RateLimiterBenchmark.atomicPermission avgt 10 0.294 ± 0.038 us/op
8+
RateLimiterBenchmark.semaphoreBasedPermission avgt 10 0.120 ± 0.018 us/op
9+
RateLimiterBenchmark.timeBasedPermission avgt 10 0.562 ± 0.045 us/op
10+
11+
RateLimiterBenchmark.atomicPermission sample 535765 1.480 ± 0.036 us/op
12+
RateLimiterBenchmark.atomicPermission:atomicPermission·p0.00 sample 0.040 us/op
13+
RateLimiterBenchmark.atomicPermission:atomicPermission·p0.50 sample 0.383 us/op
14+
RateLimiterBenchmark.atomicPermission:atomicPermission·p0.90 sample 4.288 us/op
15+
RateLimiterBenchmark.atomicPermission:atomicPermission·p0.95 sample 7.368 us/op
16+
RateLimiterBenchmark.atomicPermission:atomicPermission·p0.99 sample 14.080 us/op
17+
RateLimiterBenchmark.atomicPermission:atomicPermission·p0.999 sample 18.048 us/op
18+
RateLimiterBenchmark.atomicPermission:atomicPermission·p0.9999 sample 58.449 us/op
19+
RateLimiterBenchmark.atomicPermission:atomicPermission·p1.00 sample 1654.784 us/op
20+
RateLimiterBenchmark.semaphoreBasedPermission sample 635614 0.166 ± 0.010 us/op
21+
RateLimiterBenchmark.semaphoreBasedPermission:semaphoreBasedPermission·p0.00 sample 0.001 us/op
22+
RateLimiterBenchmark.semaphoreBasedPermission:semaphoreBasedPermission·p0.50 sample 0.135 us/op
23+
RateLimiterBenchmark.semaphoreBasedPermission:semaphoreBasedPermission·p0.90 sample 0.219 us/op
24+
RateLimiterBenchmark.semaphoreBasedPermission:semaphoreBasedPermission·p0.95 sample 0.236 us/op
25+
RateLimiterBenchmark.semaphoreBasedPermission:semaphoreBasedPermission·p0.99 sample 0.333 us/op
26+
RateLimiterBenchmark.semaphoreBasedPermission:semaphoreBasedPermission·p0.999 sample 2.468 us/op
27+
RateLimiterBenchmark.semaphoreBasedPermission:semaphoreBasedPermission·p0.9999 sample 15.519 us/op
28+
RateLimiterBenchmark.semaphoreBasedPermission:semaphoreBasedPermission·p1.00 sample 1372.160 us/op
29+
RateLimiterBenchmark.timeBasedPermission sample 553560 0.800 ± 0.053 us/op
30+
RateLimiterBenchmark.timeBasedPermission:timeBasedPermission·p0.00 sample 0.054 us/op
31+
RateLimiterBenchmark.timeBasedPermission:timeBasedPermission·p0.50 sample 0.550 us/op
32+
RateLimiterBenchmark.timeBasedPermission:timeBasedPermission·p0.90 sample 0.749 us/op
33+
RateLimiterBenchmark.timeBasedPermission:timeBasedPermission·p0.95 sample 0.826 us/op
34+
RateLimiterBenchmark.timeBasedPermission:timeBasedPermission·p0.99 sample 8.256 us/op
35+
RateLimiterBenchmark.timeBasedPermission:timeBasedPermission·p0.999 sample 33.920 us/op
36+
RateLimiterBenchmark.timeBasedPermission:timeBasedPermission·p0.9999 sample 160.221 us/op
37+
RateLimiterBenchmark.timeBasedPermission:timeBasedPermission·p1.00 sample 5742.592 us/op
38+
39+
RateLimiterBenchmark.atomicPermission ss 10 17.140 ± 5.640 us/op
40+
RateLimiterBenchmark.semaphoreBasedPermission ss 10 9.724 ± 4.602 us/op
41+
RateLimiterBenchmark.timeBasedPermission ss 10 26.875 ± 10.869 us/op

src/jmh/java/javaslang/circuitbreaker/CircuitBreakerBenchmark.java

Lines changed: 37 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -18,46 +18,40 @@
1818
*/
1919
package javaslang.circuitbreaker;
2020

21-
import org.openjdk.jmh.annotations.*;
22-
23-
import java.time.Duration;
24-
import java.util.concurrent.TimeUnit;
25-
import java.util.function.Supplier;
26-
27-
@State(Scope.Benchmark)
28-
@OutputTimeUnit(TimeUnit.MILLISECONDS)
29-
@BenchmarkMode(Mode.Throughput)
30-
public class CircuitBreakerBenchmark {
31-
32-
private CircuitBreaker circuitBreaker;
33-
private Supplier<String> supplier;
34-
private static final int ITERATION_COUNT = 10;
35-
private static final int WARMUP_COUNT = 10;
36-
private static final int THREAD_COUNT = 10;
37-
38-
@Setup
39-
public void setUp() {
40-
CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.of(CircuitBreakerConfig.custom()
41-
.failureRateThreshold(1)
42-
.waitDurationInOpenState(Duration.ofSeconds(1))
43-
.build());
44-
circuitBreaker = circuitBreakerRegistry.circuitBreaker("testCircuitBreaker");
45-
46-
supplier = CircuitBreaker.decorateSupplier(() -> {
47-
try {
48-
Thread.sleep(100);
49-
} catch (InterruptedException e) {
50-
e.printStackTrace();
51-
}
52-
return "Hello Benchmark";
53-
}, circuitBreaker);
54-
}
55-
56-
@Benchmark
57-
@Threads(value = THREAD_COUNT)
58-
@Warmup(iterations = WARMUP_COUNT)
59-
@Measurement(iterations = ITERATION_COUNT)
60-
public String invokeSupplier(){
61-
return supplier.get();
62-
}
63-
}
21+
//@State(Scope.Benchmark)
22+
//@OutputTimeUnit(TimeUnit.MILLISECONDS)
23+
//@BenchmarkMode(Mode.Throughput)
24+
//public class CircuitBreakerBenchmark {
25+
//
26+
// private CircuitBreaker circuitBreaker;
27+
// private Supplier<String> supplier;
28+
// private static final int ITERATION_COUNT = 10;
29+
// private static final int WARMUP_COUNT = 10;
30+
// private static final int THREAD_COUNT = 10;
31+
//
32+
// @Setup
33+
// public void setUp() {
34+
// CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.of(CircuitBreakerConfig.custom()
35+
// .failureRateThreshold(1)
36+
// .waitDurationInOpenState(Duration.ofSeconds(1))
37+
// .build());
38+
// circuitBreaker = circuitBreakerRegistry.circuitBreaker("testCircuitBreaker");
39+
//
40+
// supplier = CircuitBreaker.decorateSupplier(() -> {
41+
// try {
42+
// Thread.sleep(100);
43+
// } catch (InterruptedException e) {
44+
// e.printStackTrace();
45+
// }
46+
// return "Hello Benchmark";
47+
// }, circuitBreaker);
48+
// }
49+
//
50+
// @Benchmark
51+
// @Threads(value = THREAD_COUNT)
52+
// @Warmup(iterations = WARMUP_COUNT)
53+
// @Measurement(iterations = ITERATION_COUNT)
54+
// public String invokeSupplier(){
55+
// return supplier.get();
56+
// }
57+
//}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package javaslang.circuitbreaker;
2+
3+
import javaslang.ratelimiter.RateLimiter;
4+
import javaslang.ratelimiter.RateLimiterConfig;
5+
import javaslang.ratelimiter.internal.AtomicRateLimiter;
6+
import javaslang.ratelimiter.internal.SemaphoreBasedRateLimiter;
7+
import javaslang.ratelimiter.internal.TimeBasedRateLimiter;
8+
import org.openjdk.jmh.annotations.Benchmark;
9+
import org.openjdk.jmh.annotations.BenchmarkMode;
10+
import org.openjdk.jmh.annotations.Fork;
11+
import org.openjdk.jmh.annotations.Measurement;
12+
import org.openjdk.jmh.annotations.Mode;
13+
import org.openjdk.jmh.annotations.OutputTimeUnit;
14+
import org.openjdk.jmh.annotations.Scope;
15+
import org.openjdk.jmh.annotations.Setup;
16+
import org.openjdk.jmh.annotations.State;
17+
import org.openjdk.jmh.annotations.Threads;
18+
import org.openjdk.jmh.annotations.Warmup;
19+
import org.openjdk.jmh.infra.Blackhole;
20+
21+
import java.time.Duration;
22+
import java.util.concurrent.TimeUnit;
23+
import java.util.function.Supplier;
24+
25+
@State(Scope.Benchmark)
26+
@OutputTimeUnit(TimeUnit.MICROSECONDS)
27+
@BenchmarkMode(Mode.All)
28+
public class RateLimiterBenchmark {
29+
30+
public static final int FORK_COUNT = 2;
31+
private static final int WARMUP_COUNT = 10;
32+
private static final int ITERATION_COUNT = 5;
33+
private static final int THREAD_COUNT = 2;
34+
35+
private RateLimiter semaphoreBasedRateLimiter;
36+
private RateLimiter timeBasedRateLimiter;
37+
private RateLimiter atomicRateLimiter;
38+
39+
private Supplier<String> semaphoreGuardedSupplier;
40+
private Supplier<String> timeGuardedSupplier;
41+
private Supplier<String> atomicGuardedSupplier;
42+
43+
@Setup
44+
public void setUp() {
45+
RateLimiterConfig rateLimiterConfig = RateLimiterConfig.builder()
46+
.limitForPeriod(Integer.MAX_VALUE)
47+
.limitRefreshPeriod(Duration.ofNanos(10))
48+
.timeoutDuration(Duration.ofSeconds(5))
49+
.build();
50+
semaphoreBasedRateLimiter = new SemaphoreBasedRateLimiter("semaphoreBased", rateLimiterConfig);
51+
timeBasedRateLimiter = new TimeBasedRateLimiter("timeBased", rateLimiterConfig);
52+
atomicRateLimiter = new AtomicRateLimiter("atomicBased", rateLimiterConfig);
53+
54+
Supplier<String> stringSupplier = () -> {
55+
Blackhole.consumeCPU(1);
56+
return "Hello Benchmark";
57+
};
58+
semaphoreGuardedSupplier = RateLimiter.decorateSupplier(semaphoreBasedRateLimiter, stringSupplier);
59+
timeGuardedSupplier = RateLimiter.decorateSupplier(timeBasedRateLimiter, stringSupplier);
60+
atomicGuardedSupplier = RateLimiter.decorateSupplier(atomicRateLimiter, stringSupplier);
61+
}
62+
63+
@Benchmark
64+
@Threads(value = THREAD_COUNT)
65+
@Warmup(iterations = WARMUP_COUNT)
66+
@Fork(value = FORK_COUNT)
67+
@Measurement(iterations = ITERATION_COUNT)
68+
public String semaphoreBasedPermission() {
69+
return semaphoreGuardedSupplier.get();
70+
}
71+
72+
@Benchmark
73+
@Threads(value = THREAD_COUNT)
74+
@Warmup(iterations = WARMUP_COUNT)
75+
@Fork(value = FORK_COUNT)
76+
@Measurement(iterations = ITERATION_COUNT)
77+
public String timeBasedPermission() {
78+
return timeGuardedSupplier.get();
79+
}
80+
81+
@Benchmark
82+
@Threads(value = THREAD_COUNT)
83+
@Warmup(iterations = WARMUP_COUNT)
84+
@Fork(value = FORK_COUNT)
85+
@Measurement(iterations = ITERATION_COUNT)
86+
public String atomicPermission() {
87+
return atomicGuardedSupplier.get();
88+
}
89+
}

src/jmh/java/javaslang/circuitbreaker/RingBitSetBenachmark.java

Lines changed: 24 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -18,32 +18,27 @@
1818
*/
1919
package javaslang.circuitbreaker;
2020

21-
import javaslang.circuitbreaker.internal.RingBitSet;
22-
import org.openjdk.jmh.annotations.*;
23-
24-
import java.util.concurrent.TimeUnit;
25-
26-
@State(Scope.Benchmark)
27-
@OutputTimeUnit(TimeUnit.MILLISECONDS)
28-
@BenchmarkMode(Mode.Throughput)
29-
public class RingBitSetBenachmark {
30-
31-
private RingBitSet ringBitSet;
32-
private static final int ITERATION_COUNT = 10;
33-
private static final int WARMUP_COUNT = 10;
34-
private static final int THREAD_COUNT = 10;
35-
36-
@Setup
37-
public void setUp() {
38-
ringBitSet = new RingBitSet(1000);
39-
}
40-
41-
@Benchmark
42-
@Threads(value = THREAD_COUNT)
43-
@Warmup(iterations = WARMUP_COUNT)
44-
@Measurement(iterations = ITERATION_COUNT)
45-
public void setBits(){
46-
ringBitSet.setNextBit(true);
47-
ringBitSet.setNextBit(false);
48-
}
49-
}
21+
//@State(Scope.Benchmark)
22+
//@OutputTimeUnit(TimeUnit.MILLISECONDS)
23+
//@BenchmarkMode(Mode.Throughput)
24+
//public class RingBitSetBenachmark {
25+
//
26+
// private RingBitSet ringBitSet;
27+
// private static final int ITERATION_COUNT = 10;
28+
// private static final int WARMUP_COUNT = 10;
29+
// private static final int THREAD_COUNT = 10;
30+
//
31+
// @Setup
32+
// public void setUp() {
33+
// ringBitSet = new RingBitSet(1000);
34+
// }
35+
//
36+
// @Benchmark
37+
// @Threads(value = THREAD_COUNT)
38+
// @Warmup(iterations = WARMUP_COUNT)
39+
// @Measurement(iterations = ITERATION_COUNT)
40+
// public void setBits(){
41+
// ringBitSet.setNextBit(true);
42+
// ringBitSet.setNextBit(false);
43+
// }
44+
//}

0 commit comments

Comments
 (0)