Skip to content

Commit c471e7c

Browse files
author
Mikhail Chernyakov
authored
add jmh tests #1 (#8)
* add jmh tests * build fix * readme fix * initial capacity = num_values (for jmh tests)
1 parent da3b679 commit c471e7c

File tree

7 files changed

+305
-13
lines changed

7 files changed

+305
-13
lines changed

README.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,57 @@ Currently, we offer two locking modes:
7676
- `blocking` (default),
7777
- `busy-waiting`.
7878

79+
### JMH tests
80+
81+
For running JMH tests just execute:
82+
```bash
83+
./gradlew jmh
84+
```
85+
86+
Results for `FastutilWrapper BusyWaiting mode` vs `FastutilWrapper Default mode` vs [java.util wrappers](https://docs.oracle.com/javase/tutorial/collections/implementations/wrapper.html)
87+
88+
Throughput (more is better)
89+
90+
```shell
91+
Benchmark Mode Cnt Score Error Units
92+
93+
FastutilWrapperBusyWaitingBenchmark.testRandomAllOpsThroughput thrpt 15 14517457,055 ? 795637,784 ops/s
94+
FastutilWrapperBusyWaitingBenchmark.testRandomGetThroughput thrpt 15 16610181,320 ? 1456776,589 ops/s
95+
FastutilWrapperBusyWaitingBenchmark.testRandomPutThroughput thrpt 13 11706178,916 ? 2547333,524 ops/s
96+
97+
FastutilWrapperDefaultBenchmark.testRandomAllOpsThroughput thrpt 15 7385357,514 ? 1127356,032 ops/s
98+
FastutilWrapperDefaultBenchmark.testRandomGetThroughput thrpt 15 16190621,923 ? 1836415,022 ops/s
99+
FastutilWrapperDefaultBenchmark.testRandomPutThroughput thrpt 15 8945369,395 ? 1225460,217 ops/s
100+
101+
JavaUtilWrapperBenchmark.testRandomAllOpsThroughput thrpt 15 4921201,916 ? 410471,239 ops/s
102+
JavaUtilWrapperBenchmark.testRandomGetThroughput thrpt 15 7827123,690 ? 557193,670 ops/s
103+
JavaUtilWrapperBenchmark.testRandomPutThroughput thrpt 15 4832517,371 ? 1122344,647 ops/s
104+
```
105+
AverageTime per ops (less is better)
106+
107+
```shell
108+
Benchmark Mode Cnt Score Error Units
109+
110+
FastutilWrapperBusyWaitingBenchmark.testRandomAllOpsAvgTime avgt 15 268,790 ? 22,526 ns/op
111+
FastutilWrapperBusyWaitingBenchmark.testRandomGetAvgTime avgt 15 231,552 ? 16,116 ns/op
112+
FastutilWrapperBusyWaitingBenchmark.testRandomPutAvgTime avgt 10 292,246 ? 49,757 ns/op
113+
114+
FastutilWrapperDefaultBenchmark.testRandomAllOpsAvgTime avgt 15 467,381 ? 9,790 ns/op
115+
FastutilWrapperDefaultBenchmark.testRandomGetAvgTime avgt 15 237,683 ? 14,167 ns/op
116+
FastutilWrapperDefaultBenchmark.testRandomPutAvgTime avgt 15 427,441 ? 25,116 ns/op
117+
118+
JavaUtilWrapperBenchmark.testRandomAllOpsAvgTime avgt 15 781,869 ? 191,081 ns/op
119+
JavaUtilWrapperBenchmark.testRandomGetAvgTime avgt 15 470,869 ? 33,198 ns/op
120+
JavaUtilWrapperBenchmark.testRandomPutAvgTime avgt 15 964,613 ? 422,648 ns/op
121+
```
122+
123+
The machine
124+
```shell
125+
MacBook Pro (15-inch, 2019)
126+
Processor 2,6 GHz 6-Core Intel Core i7
127+
Memory 16 GB 2400 MHz DDR4
128+
```
129+
79130
## Maintainers
80131
A-Z surname order
81132

build.gradle

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,39 @@
1-
buildscript {
1+
plugins {
2+
id "idea"
3+
id "java-library"
4+
id "me.champeau.jmh" version "0.6.6"
5+
id "com.vanniktech.maven.publish" version "0.18.0"
6+
}
7+
8+
allprojects {
29
repositories {
310
mavenLocal()
411
mavenCentral()
12+
maven {
13+
url "https://plugins.gradle.org/m2/"
14+
}
515
}
6-
dependencies {
7-
classpath 'com.vanniktech:gradle-maven-publish-plugin:0.18.0'
8-
}
9-
}
10-
11-
repositories {
12-
mavenCentral()
1316
}
1417

15-
apply plugin: 'java'
16-
apply plugin: "com.vanniktech.maven.publish"
17-
1818
group 'com.trivago'
1919
version '0.1.1-SNAPSHOT'
2020

2121
sourceCompatibility = 1.8
2222
targetCompatibility = 1.8
2323

24+
sourceSets {
25+
jmh {
26+
java.srcDirs = ['src/jmh/java']
27+
resources.srcDirs = ['src/jmh/resources']
28+
compileClasspath += sourceSets.main.runtimeClasspath
29+
}
30+
}
31+
2432
dependencies {
2533
implementation group: 'it.unimi.dsi', name: 'fastutil', version: '8.5.6'
2634

27-
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
28-
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
35+
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2'
36+
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.2'
2937
}
3038

3139
test {
@@ -47,3 +55,9 @@ publishing {
4755
}
4856
}
4957
}
58+
59+
// ./gradlew jmh
60+
jmh {
61+
jvmArgs = ["-Xms3072m","-Xmx3072m"]
62+
duplicateClassesStrategy = DuplicatesStrategy.EXCLUDE
63+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package com.trivago.kangaroo;
2+
3+
import com.trivago.fastutilconcurrentwrapper.ConcurrentLongLongMapBuilder;
4+
import com.trivago.fastutilconcurrentwrapper.LongLongMap;
5+
6+
import java.util.concurrent.ThreadLocalRandom;
7+
8+
public abstract class AbstractBenchHelper extends AbstractCommonBenchHelper {
9+
10+
protected static final int NUM_VALUES = 1_000_000;
11+
12+
protected LongLongMap map;
13+
14+
public void initAndLoadData(ConcurrentLongLongMapBuilder.MapMode mode) {
15+
if (mode.equals(ConcurrentLongLongMapBuilder.MapMode.BUSY_WAITING)) {
16+
map = ConcurrentLongLongMapBuilder.newBuilder()
17+
.withBuckets(16)
18+
.withInitialCapacity(NUM_VALUES)
19+
.withMode(ConcurrentLongLongMapBuilder.MapMode.BUSY_WAITING)
20+
.withLoadFactor(0.8f)
21+
.build();
22+
} else {
23+
map = ConcurrentLongLongMapBuilder.newBuilder()
24+
.withBuckets(16)
25+
.withInitialCapacity(NUM_VALUES)
26+
.withLoadFactor(0.8f)
27+
.build();
28+
}
29+
30+
for (int i = 0; i < NUM_VALUES; i++) {
31+
long key = ThreadLocalRandom.current().nextLong();
32+
long value = ThreadLocalRandom.current().nextLong();
33+
map.put(key, value);
34+
}
35+
}
36+
37+
public void testGet() {
38+
long key = ThreadLocalRandom.current().nextLong();
39+
map.get(key);
40+
}
41+
42+
public void testPut() {
43+
long key = ThreadLocalRandom.current().nextLong();
44+
long value = ThreadLocalRandom.current().nextLong();
45+
map.put(key, value);
46+
}
47+
48+
public void testAllOps() {
49+
int op = ThreadLocalRandom.current().nextInt(3);
50+
long key = ThreadLocalRandom.current().nextLong();
51+
switch (op) {
52+
case 1:
53+
long value = ThreadLocalRandom.current().nextLong();
54+
map.put(key, value);
55+
break;
56+
case 2:
57+
map.remove(key);
58+
break;
59+
default:
60+
map.get(key);
61+
break;
62+
}
63+
}
64+
65+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package com.trivago.kangaroo;
2+
3+
import org.openjdk.jmh.annotations.Benchmark;
4+
import org.openjdk.jmh.annotations.BenchmarkMode;
5+
import org.openjdk.jmh.annotations.Mode;
6+
import org.openjdk.jmh.annotations.OutputTimeUnit;
7+
import org.openjdk.jmh.annotations.Threads;
8+
9+
import java.util.concurrent.TimeUnit;
10+
11+
abstract public class AbstractCommonBenchHelper {
12+
@Threads(4)
13+
@Benchmark
14+
@BenchmarkMode(Mode.Throughput)
15+
public void testRandomGetThroughput() {
16+
testGet();
17+
}
18+
19+
@Threads(4)
20+
@Benchmark
21+
@BenchmarkMode(Mode.Throughput)
22+
public void testRandomPutThroughput() {
23+
testPut();
24+
}
25+
26+
@Threads(4)
27+
@Benchmark
28+
@BenchmarkMode(Mode.Throughput)
29+
public void testRandomAllOpsThroughput() {
30+
testAllOps();
31+
}
32+
33+
@Threads(4)
34+
@Benchmark
35+
@BenchmarkMode(Mode.AverageTime)
36+
@OutputTimeUnit(TimeUnit.NANOSECONDS)
37+
public void testRandomGetAvgTime() {
38+
testGet();
39+
}
40+
41+
@Threads(4)
42+
@Benchmark
43+
@BenchmarkMode(Mode.AverageTime)
44+
@OutputTimeUnit(TimeUnit.NANOSECONDS)
45+
public void testRandomPutAvgTime() {
46+
testPut();
47+
}
48+
49+
@Threads(4)
50+
@Benchmark
51+
@BenchmarkMode(Mode.AverageTime)
52+
@OutputTimeUnit(TimeUnit.NANOSECONDS)
53+
public void testRandomAllOpsAvgTime() {
54+
testAllOps();
55+
}
56+
57+
abstract public void testGet();
58+
59+
abstract public void testPut();
60+
61+
abstract public void testAllOps();
62+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.trivago.kangaroo;
2+
3+
import com.trivago.fastutilconcurrentwrapper.ConcurrentLongLongMapBuilder;
4+
import org.openjdk.jmh.annotations.Level;
5+
import org.openjdk.jmh.annotations.Measurement;
6+
import org.openjdk.jmh.annotations.Scope;
7+
import org.openjdk.jmh.annotations.Setup;
8+
import org.openjdk.jmh.annotations.State;
9+
import org.openjdk.jmh.annotations.Warmup;
10+
11+
@State(Scope.Benchmark)
12+
@Warmup(iterations = 3, time = 1)
13+
@Measurement(iterations = 3, time = 2)
14+
public class FastutilWrapperBusyWaitingBenchmark extends AbstractBenchHelper {
15+
16+
@Setup(Level.Trial)
17+
public void loadData() {
18+
super.initAndLoadData(ConcurrentLongLongMapBuilder.MapMode.BUSY_WAITING);
19+
}
20+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.trivago.kangaroo;
2+
3+
import com.trivago.fastutilconcurrentwrapper.ConcurrentLongLongMapBuilder;
4+
import org.openjdk.jmh.annotations.Level;
5+
import org.openjdk.jmh.annotations.Measurement;
6+
import org.openjdk.jmh.annotations.Scope;
7+
import org.openjdk.jmh.annotations.Setup;
8+
import org.openjdk.jmh.annotations.State;
9+
import org.openjdk.jmh.annotations.Warmup;
10+
11+
@State(Scope.Benchmark)
12+
@Warmup(iterations = 3, time = 1)
13+
@Measurement(iterations = 3, time = 2)
14+
public class FastutilWrapperDefaultBenchmark extends AbstractBenchHelper {
15+
16+
@Setup(Level.Trial)
17+
public void loadData() {
18+
super.initAndLoadData(ConcurrentLongLongMapBuilder.MapMode.BLOCKING);
19+
}
20+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package com.trivago.kangaroo;
2+
3+
import it.unimi.dsi.fastutil.longs.Long2LongOpenHashMap;
4+
import org.openjdk.jmh.annotations.Level;
5+
import org.openjdk.jmh.annotations.Measurement;
6+
import org.openjdk.jmh.annotations.Scope;
7+
import org.openjdk.jmh.annotations.Setup;
8+
import org.openjdk.jmh.annotations.State;
9+
import org.openjdk.jmh.annotations.Warmup;
10+
11+
import java.util.Collections;
12+
import java.util.Map;
13+
import java.util.concurrent.ThreadLocalRandom;
14+
15+
@State(Scope.Benchmark)
16+
@Warmup(iterations = 3, time = 1)
17+
@Measurement(iterations = 3, time = 2)
18+
public class JavaUtilWrapperBenchmark extends AbstractCommonBenchHelper {
19+
20+
Map<Long, Long> map;
21+
22+
@Setup(Level.Trial)
23+
public void loadData() {
24+
Long2LongOpenHashMap m = new Long2LongOpenHashMap(AbstractBenchHelper.NUM_VALUES, 0.8f);
25+
for (int i = 0; i < AbstractBenchHelper.NUM_VALUES; i++) {
26+
long key = ThreadLocalRandom.current().nextLong();
27+
long value = ThreadLocalRandom.current().nextLong();
28+
m.put(key, value);
29+
}
30+
map = Collections.synchronizedMap(m);
31+
}
32+
33+
public void testGet() {
34+
long key = ThreadLocalRandom.current().nextLong();
35+
map.get(key);
36+
}
37+
38+
public void testPut() {
39+
long key = ThreadLocalRandom.current().nextLong();
40+
long value = ThreadLocalRandom.current().nextLong();
41+
map.put(key, value);
42+
}
43+
44+
public void testAllOps() {
45+
int op = ThreadLocalRandom.current().nextInt(3);
46+
long key = ThreadLocalRandom.current().nextLong();
47+
switch (op) {
48+
case 1:
49+
long value = ThreadLocalRandom.current().nextLong();
50+
map.put(key, value);
51+
break;
52+
case 2:
53+
map.remove(key);
54+
break;
55+
default:
56+
map.get(key);
57+
break;
58+
}
59+
}
60+
}

0 commit comments

Comments
 (0)