Commit 0a436290 authored by Tigran Mkrtchyan's avatar Tigran Mkrtchyan
Browse files

nlm: add throughput test for lock manager

Motivation:

 - performance benchmarking
 - getting in touch with JMH

Modification:
Add throughput test for lock manager. Introduce a dedicated profile to
run benchmark tests.

```
$ mvn clean verify -Pbenchmark

....

Result "org.dcache.nfs.benchmarks.ConcurrentLockManagerBenchmark.benchmarkConcurrentLocking":
  1574556.068 ±(99.9%) 98632.233 ops/s [Average]
  (min, avg, max) = (1078256.296, 1574556.068, 1735655.142), stdev = 131671.209
  CI (99.9%): [1475923.835, 1673188.301] (assumes normal distribution)

$
```

Result:
automated performance monitoring can be integrated into CI.

Acked-by: Albert Rossi
Target: master
parent 7c7714d5
......@@ -10,6 +10,11 @@ Building from sources
To build nfs4j from source code Java8 and Maven3 are required.
To run benchmarks:
```
mvn verify -Pbenchmark
```
Implementing own NFS server
---------------------------
......
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.dcache</groupId>
<artifactId>nfs4j</artifactId>
<version>0.19.0-SNAPSHOT</version>
</parent>
<groupId>org.dcache</groupId>
<artifactId>benchmarks</artifactId>
<packaging>jar</packaging>
<profiles>
<profile>
<id>benchmark</id>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<executions>
<execution>
<goals>
<goal>exec</goal>
</goals>
<phase>integration-test</phase>
</execution>
</executions>
<configuration>
<executable>java</executable>
<classpathScope>test</classpathScope>
<arguments>
<argument>-classpath</argument>
<classpath />
<argument>org.dcache.nfs.benchmarks.BenchmarkRunner</argument>
<argument>.*</argument>
</arguments>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<!--
EXTERNAL DEPENDENCIES
-->
<dependencies>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
</dependency>
<dependency>
<groupId>org.dcache</groupId>
<artifactId>nfs4j-core</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
package org.dcache.nfs.benchmarks;
import org.openjdk.jmh.results.format.ResultFormatType;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
/**
*
*/
public class BenchmarkRunner {
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(ConcurrentLockManagerBenchmark.class.getSimpleName())
.resultFormat(ResultFormatType.JSON)
.build();
new Runner(opt).run();
}
}
package org.dcache.nfs.benchmarks;
import java.nio.charset.StandardCharsets;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import org.dcache.nfs.v4.StateOwner;
import org.dcache.nfs.v4.nlm.LockException;
import org.dcache.nfs.v4.nlm.LockManager;
import org.dcache.nfs.v4.nlm.NlmLock;
import org.dcache.nfs.v4.nlm.SimpleLm;
import org.dcache.nfs.v4.xdr.clientid4;
import org.dcache.nfs.v4.xdr.nfs_lock_type4;
import org.dcache.nfs.v4.xdr.state_owner4;
import org.openjdk.jmh.annotations.*;
@BenchmarkMode(Mode.Throughput)
public class ConcurrentLockManagerBenchmark {
/*
* Lock manage object. One instance per benchmark.
*/
@State(Scope.Benchmark)
public static class LockManagerHolder {
private LockManager lm;
@Setup
public void setUp() {
lm = new SimpleLm();
}
public LockManager getLockManager() {
return lm;
}
}
/*
* File id object. One per thread. Created in advance to reduce allocation overhead.
*/
@State(Scope.Thread)
public static class FileHolder {
private final Random random = ThreadLocalRandom.current();
private final byte[] file1 = new byte[16];
public FileHolder() {
random.nextBytes(file1);
}
public byte[] getFile() {
return file1;
}
}
@Benchmark
@Threads(16)
@Warmup(iterations = 5, time = 100, timeUnit = TimeUnit.MILLISECONDS)
public NlmLock benchmarkConcurrentLocking(LockManagerHolder lmh, FileHolder fh) throws LockException {
NlmLock lock = new LockBuilder()
.withOwner("owner1")
.from(0)
.length(1)
.forWrite()
.build();
lmh.getLockManager().lock(fh.getFile(), lock);
return lock;
}
public static class LockBuilder {
private long offset;
private long length;
private StateOwner owner;
private int lockType;
LockBuilder withOwner(String owner) {
state_owner4 so = new state_owner4();
so.owner = owner.getBytes(StandardCharsets.UTF_8);
so.clientid = new clientid4(1);
this.owner = new StateOwner(so, 1);
return this;
}
LockBuilder from(long offset) {
this.offset = offset;
return this;
}
LockBuilder length(long length) {
this.length = length;
return this;
}
LockBuilder forRead() {
this.lockType = nfs_lock_type4.READ_LT;
return this;
}
LockBuilder forWrite() {
this.lockType = nfs_lock_type4.WRITE_LT;
return this;
}
NlmLock build() {
return new NlmLock(owner, lockType, offset, length);
}
}
}
......@@ -70,6 +70,16 @@
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
......
......@@ -45,7 +45,15 @@ public class SimpleLm extends AbstractLockManager {
*
* FIXME: get number of threads from RPC service.
*/
private final Striped<Lock> objLock = Striped.lock(Runtime.getRuntime().availableProcessors() * 4);
private final Striped<Lock> objLock;
public SimpleLm() {
this(Runtime.getRuntime().availableProcessors()*4);
}
public SimpleLm(int concurrency) {
objLock = Striped.lock(concurrency);
}
/**
* Exclusive lock on objects locks.
......
......@@ -40,6 +40,7 @@
<module>basic-client</module>
<module>spring</module>
<module>dlm</module>
<module>benchmarks</module>
</modules>
<build>
......@@ -189,6 +190,16 @@
<artifactId>je</artifactId>
<version>7.3.7</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>1.21</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>1.21</version>
</dependency>
</dependencies>
</dependencyManagement>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment