Skip to content

Commit 66fa301

Browse files
authored
Merge pull request #12 from patrickfav/feat-11-jmh-benchmark
Add JMH Benchmark
2 parents 30dd367 + 6cd1c12 commit 66fa301

6 files changed

Lines changed: 202 additions & 3 deletions

File tree

CHANGELOG

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
* allow actual 2^31 rounds (fix integer overflow issue with `1<<31`) #7
66
* use Apache v2 compatible Radix 64 impl and skip OpenJDK one #8
7+
* add JMH benchmark module #11
78

89
## v0.4.0
910

README.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,12 @@ Compare this to other benchmarks, [like this one in node.js](https://github.com/
270270
**Disclaimer:** Micro benchmarks are [usually a really bad way to measure performance](https://mrale.ph/blog/2012/12/15/microbenchmarks-fairy-tale.html).
271271
These numbers are only informal tests and should not be used to derive any security relevant decisions.
272272

273+
#### JMH Benchmark
274+
275+
Additionally there is JMH benchmark module, which is probably better than my home-brew micro benchmark. Build it with
276+
maven `./mvnw clean install` (you may want to disable jar signing with `<project.skipJarSign>` property) and execute
277+
it with `java -jar modules/benchmark-jmh/target/benchmark-jmh-x.y.z-full.jar`.
278+
273279
### Test Vectors and Reference Implementations
274280

275281
This implementation is tested against the bcrypt implementation jBcrypt and Bouncy Castle. It includes test vectors
@@ -366,7 +372,7 @@ If you want to skip jar signing just change the skip configuration in the
366372

367373
Use the Maven wrapper to create a jar including all dependencies
368374

369-
mvnw clean install
375+
./mvnw clean install
370376

371377
## Tech Stack
372378

modules/bcrypt/pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,13 +147,13 @@
147147
<dependency>
148148
<groupId>org.mindrot</groupId>
149149
<artifactId>jbcrypt</artifactId>
150-
<version>0.4</version>
150+
<version>${project.jbcryptVersion}</version>
151151
<scope>test</scope>
152152
</dependency>
153153
<dependency>
154154
<groupId>org.bouncycastle</groupId>
155155
<artifactId>bcprov-jdk15on</artifactId>
156-
<version>1.60</version>
156+
<version>${project.bcVersion}</version>
157157
<scope>test</scope>
158158
</dependency>
159159
<dependency>

modules/benchmark-jmh/pom.xml

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<parent>
8+
<artifactId>bcrypt-parent</artifactId>
9+
<groupId>at.favre.lib</groupId>
10+
<version>0.5.0</version>
11+
<relativePath>../../</relativePath>
12+
</parent>
13+
14+
<artifactId>benchmark-jmh</artifactId>
15+
<packaging>jar</packaging>
16+
17+
<name>BCrypt JMH Benchmark</name>
18+
19+
<properties>
20+
<maven.deploy.skip>true</maven.deploy.skip>
21+
<jmh.version>1.21</jmh.version>
22+
</properties>
23+
24+
<build>
25+
<plugins>
26+
<plugin>
27+
<groupId>org.apache.maven.plugins</groupId>
28+
<artifactId>maven-checkstyle-plugin</artifactId>
29+
<configuration>
30+
<skip>true</skip>
31+
</configuration>
32+
</plugin>
33+
<plugin>
34+
<groupId>org.jacoco</groupId>
35+
<artifactId>jacoco-maven-plugin</artifactId>
36+
<configuration>
37+
<skip>true</skip>
38+
</configuration>
39+
</plugin>
40+
<plugin>
41+
<groupId>com.github.chrisdchristo</groupId>
42+
<artifactId>capsule-maven-plugin</artifactId>
43+
<version>1.5.1</version>
44+
<configuration>
45+
<appClass>org.openjdk.jmh.Main</appClass>
46+
<fileDesc>-full</fileDesc>
47+
<type>fat</type>
48+
</configuration>
49+
<executions>
50+
<execution>
51+
<id>build-fat-jar</id>
52+
<phase>package</phase>
53+
<goals>
54+
<goal>build</goal>
55+
</goals>
56+
</execution>
57+
</executions>
58+
</plugin>
59+
</plugins>
60+
</build>
61+
62+
<dependencies>
63+
<dependency>
64+
<groupId>org.openjdk.jmh</groupId>
65+
<artifactId>jmh-core</artifactId>
66+
<version>${jmh.version}</version>
67+
</dependency>
68+
<dependency>
69+
<groupId>org.openjdk.jmh</groupId>
70+
<artifactId>jmh-generator-annprocess</artifactId>
71+
<version>${jmh.version}</version>
72+
<scope>provided</scope>
73+
</dependency>
74+
<dependency>
75+
<groupId>at.favre.lib</groupId>
76+
<artifactId>bcrypt</artifactId>
77+
<version>0.5.0</version>
78+
<classifier>optimized</classifier>
79+
</dependency>
80+
<dependency>
81+
<groupId>org.mindrot</groupId>
82+
<artifactId>jbcrypt</artifactId>
83+
<version>${project.jbcryptVersion}</version>
84+
</dependency>
85+
<dependency>
86+
<groupId>org.bouncycastle</groupId>
87+
<artifactId>bcprov-jdk15on</artifactId>
88+
<version>${project.bcVersion}</version>
89+
</dependency>
90+
<dependency>
91+
<groupId>com.github.fzakaria</groupId>
92+
<artifactId>ascii85</artifactId>
93+
<version>1.1</version>
94+
</dependency>
95+
</dependencies>
96+
</project>
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package at.favre.lib.crypto.bcrypt.benchmark;
2+
3+
import at.favre.lib.bytes.BinaryToTextEncoding;
4+
import at.favre.lib.bytes.Bytes;
5+
import at.favre.lib.crypto.bcrypt.BCrypt;
6+
import com.github.fzakaria.ascii85.Ascii85;
7+
import org.openjdk.jmh.annotations.*;
8+
9+
import java.nio.ByteOrder;
10+
import java.nio.charset.StandardCharsets;
11+
import java.util.concurrent.TimeUnit;
12+
13+
@SuppressWarnings("CheckStyle")
14+
@State(Scope.Thread)
15+
@Fork(1)
16+
@Warmup(iterations = 2, time = 4)
17+
@Measurement(iterations = 3, time = 12)
18+
@BenchmarkMode(Mode.AverageTime)
19+
@OutputTimeUnit(TimeUnit.MILLISECONDS)
20+
//CHECKSTYLE.OFF
21+
public class BcryptBenchmark {
22+
23+
private AbstractBcrypt favreBcrypt;
24+
private AbstractBcrypt jBcrypt;
25+
private AbstractBcrypt bcBcrypt;
26+
private BinaryToTextEncoding.Encoder ascii85 = new BinaryToTextEncoding.Encoder() {
27+
@Override
28+
public String encode(byte[] bytes, ByteOrder byteOrder) {
29+
return Ascii85.encode(bytes);
30+
}
31+
};
32+
33+
@Param({"10", "12"})
34+
private int cost;
35+
private byte[] pw;
36+
37+
@Setup(Level.Trial)
38+
public void setupBenchmark() {
39+
favreBcrypt = new FavreBcrypt();
40+
jBcrypt = new JBcrypt();
41+
bcBcrypt = new BC();
42+
}
43+
44+
@Setup(Level.Invocation)
45+
public void setup() {
46+
pw = Bytes.random(36).encode(ascii85).getBytes(StandardCharsets.UTF_8);
47+
}
48+
49+
@Benchmark
50+
public byte[] benchmarkFavreBcrypt() {
51+
return benchmark(favreBcrypt, cost, pw);
52+
}
53+
54+
//@Benchmark
55+
public byte[] benchmarkJBcrypt() {
56+
return benchmark(jBcrypt, cost, pw);
57+
}
58+
59+
//@Benchmark
60+
public byte[] benchmarkBcBcrypt() {
61+
return benchmark(bcBcrypt, cost, pw);
62+
}
63+
64+
private byte[] benchmark(AbstractBcrypt bcrypt, int logRounds, byte[] pw) {
65+
return bcrypt.bcrypt(logRounds, pw);
66+
}
67+
68+
static final class FavreBcrypt implements AbstractBcrypt {
69+
@Override
70+
public byte[] bcrypt(int cost, byte[] password) {
71+
return BCrypt.withDefaults().hash(cost, password);
72+
}
73+
}
74+
75+
static final class JBcrypt implements AbstractBcrypt {
76+
@Override
77+
public byte[] bcrypt(int cost, byte[] password) {
78+
return org.mindrot.jbcrypt.BCrypt.hashpw(new String(password, StandardCharsets.UTF_8), org.mindrot.jbcrypt.BCrypt.gensalt(cost)).getBytes(StandardCharsets.UTF_8);
79+
}
80+
}
81+
82+
static final class BC implements AbstractBcrypt {
83+
@Override
84+
public byte[] bcrypt(int cost, byte[] password) {
85+
return org.bouncycastle.crypto.generators.BCrypt.generate(Bytes.from(password).append((byte) 0).array(), Bytes.random(16).array(), cost);
86+
}
87+
}
88+
89+
interface AbstractBcrypt {
90+
byte[] bcrypt(int cost, byte[] password);
91+
}
92+
}
93+
//CHECKSTYLE.ON

pom.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,14 @@
1818
<modules>
1919
<module>modules/bcrypt</module>
2020
<module>modules/bcrypt-cli</module>
21+
<module>modules/benchmark-jmh</module>
2122
</modules>
2223

2324
<properties>
2425
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
2526
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
27+
<project.jbcryptVersion>0.4</project.jbcryptVersion>
28+
<project.bcVersion>1.60</project.bcVersion>
2629
<project.skipJarSign>false
2730
</project.skipJarSign> <!-- set this to true if fail because of missing credentials -->
2831
</properties>

0 commit comments

Comments
 (0)