aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--microbenchmark-template/README.md1
-rw-r--r--microbenchmark-template/pom.xml85
-rwxr-xr-xmicrobenchmark-template/run.sh4
-rw-r--r--microbenchmark-template/src/main/java/org/sonar/microbenchmark/SerializationBenchmark.java162
-rw-r--r--microbenchmark-template/src/test/java/org/sonar/microbenchmark/SerializationBenchmarkTest.java77
5 files changed, 329 insertions, 0 deletions
diff --git a/microbenchmark-template/README.md b/microbenchmark-template/README.md
new file mode 100644
index 00000000000..8beaf58c640
--- /dev/null
+++ b/microbenchmark-template/README.md
@@ -0,0 +1 @@
+Template for quickly write micro-benchmarks with JMH
diff --git a/microbenchmark-template/pom.xml b/microbenchmark-template/pom.xml
new file mode 100644
index 00000000000..32659e1d664
--- /dev/null
+++ b/microbenchmark-template/pom.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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.codehaus.sonar</groupId>
+ <artifactId>sonar</artifactId>
+ <version>5.1-SNAPSHOT</version>
+ </parent>
+ <artifactId>microbenchmark-template</artifactId>
+ <packaging>jar</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sonar-batch-protocol</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.esotericsoftware</groupId>
+ <artifactId>kryo-shaded</artifactId>
+ <version>3.0.0</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sonar-plugin-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.openjdk.jmh</groupId>
+ <artifactId>jmh-core</artifactId>
+ <version>${jmh.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.openjdk.jmh</groupId>
+ <artifactId>jmh-generator-annprocess</artifactId>
+ <version>${jmh.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sonar-testing-harness</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <jmh.version>1.1.1</jmh.version>
+ <uberjar.name>microbenchmark</uberjar.name>
+ </properties>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-shade-plugin</artifactId>
+ <version>2.2</version>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>shade</goal>
+ </goals>
+ <configuration>
+ <finalName>${uberjar.name}</finalName>
+ <transformers>
+ <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+ <mainClass>org.openjdk.jmh.Main</mainClass>
+ </transformer>
+ </transformers>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/microbenchmark-template/run.sh b/microbenchmark-template/run.sh
new file mode 100755
index 00000000000..10d0c60f6b3
--- /dev/null
+++ b/microbenchmark-template/run.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+mvn clean install
+java -jar target/microbenchmark.jar -i 5 -wi 5 -f 5
diff --git a/microbenchmark-template/src/main/java/org/sonar/microbenchmark/SerializationBenchmark.java b/microbenchmark-template/src/main/java/org/sonar/microbenchmark/SerializationBenchmark.java
new file mode 100644
index 00000000000..c392d7cf841
--- /dev/null
+++ b/microbenchmark-template/src/main/java/org/sonar/microbenchmark/SerializationBenchmark.java
@@ -0,0 +1,162 @@
+/*
+ * markdown-benchmark
+ * Copyright (C) 2009 ${owner}
+ * dev@sonar.codehaus.org
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.microbenchmark;
+
+import com.esotericsoftware.kryo.Kryo;
+import com.esotericsoftware.kryo.io.Output;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.stream.JsonWriter;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.sonar.batch.protocol.Constants;
+import org.sonar.batch.protocol.output.BatchOutput;
+
+import java.io.BufferedOutputStream;
+import java.io.BufferedWriter;
+import java.io.Externalizable;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.io.Serializable;
+
+@State(Scope.Thread)
+public class SerializationBenchmark {
+
+ File outputFile;
+ private final Gson gson = new GsonBuilder().create();
+
+ @Setup
+ public void setup() throws Exception {
+ outputFile = File.createTempFile("microbenchmark", ".out");
+ }
+
+ @Benchmark
+ public void write_gson() throws Exception {
+ JsonWriter writer = new JsonWriter(new BufferedWriter(new FileWriter(outputFile, false)));
+ writer.beginArray();
+ for (int i = 0; i < 10000; i++) {
+ Issue issue = new Issue();
+ issue.uuid = "UUID_" + i;
+ issue.severity = "BLOCKER";
+ issue.message = "this is the message of issue " + i;
+ issue.line = i;
+ issue.author = "someone";
+ gson.toJson(issue, Issue.class, writer);
+ }
+ writer.endArray();
+ writer.close();
+ }
+
+ @Benchmark
+ public void write_protobuf() throws Exception {
+ // Write stream of objects with delimiter
+ // An alternative can be http://stackoverflow.com/a/21870564/229031
+ try (OutputStream out = new BufferedOutputStream(new FileOutputStream(outputFile, false))) {
+ for (int i = 0; i < 10000; i++) {
+ BatchOutput.ReportIssue.Builder issueBuilder = BatchOutput.ReportIssue.newBuilder();
+ issueBuilder.setUuid("UUID_" + i);
+ issueBuilder.setSeverity(Constants.Severity.BLOCKER);
+ issueBuilder.setMsg("this is the message of issue " + i);
+ issueBuilder.setLine(i);
+ issueBuilder.setAuthorLogin("someone");
+ issueBuilder.build().writeDelimitedTo(out);
+ }
+ }
+ }
+
+ @Benchmark
+ public void write_serializable() throws Exception {
+ try (ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(outputFile, false)))) {
+ for (int i = 0; i < 10000; i++) {
+ Issue issue = new Issue();
+ issue.uuid = "UUID_" + i;
+ issue.severity = "BLOCKER";
+ issue.message = "this is the message of issue " + i;
+ issue.line = i;
+ issue.author = "someone";
+ out.writeObject(issue);
+ }
+ }
+ }
+
+ @Benchmark
+ public void write_externalizable() throws Exception {
+ try (ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(outputFile, false)))) {
+ for (int i = 0; i < 10000; i++) {
+ ExternalizableIssue issue = new ExternalizableIssue();
+ issue.uuid = "UUID_" + i;
+ issue.severity = "BLOCKER";
+ issue.message = "this is the message of issue " + i;
+ issue.line = i;
+ issue.author = "someone";
+ out.writeObject(issue);
+ }
+ }
+ }
+
+ @Benchmark
+ public void write_kryo() throws Exception {
+ Kryo kryo = new Kryo();
+ OutputStream stream = new BufferedOutputStream(new FileOutputStream(outputFile, false));
+ Output output = new Output(stream);
+ for (int i = 0; i < 10000; i++) {
+ Issue issue = new Issue();
+ issue.uuid = "UUID_" + i;
+ issue.severity = "BLOCKER";
+ issue.message = "this is the message of issue " + i;
+ issue.line = i;
+ issue.author = "someone";
+ kryo.writeObject(output, issue);
+ }
+ output.close();
+ }
+
+ public static class Issue implements Serializable {
+ String uuid, severity, message, author;
+ int line;
+ }
+
+ public static class ExternalizableIssue implements Externalizable {
+ String uuid, severity, message, author;
+ int line;
+
+ @Override
+ public void writeExternal(ObjectOutput out) throws IOException {
+ out.writeObject(uuid);
+ out.writeObject(severity);
+ out.writeObject(message);
+ out.writeObject(author);
+ out.writeInt(line);
+ }
+
+ @Override
+ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ throw new UnsupportedOperationException();
+ }
+ }
+}
diff --git a/microbenchmark-template/src/test/java/org/sonar/microbenchmark/SerializationBenchmarkTest.java b/microbenchmark-template/src/test/java/org/sonar/microbenchmark/SerializationBenchmarkTest.java
new file mode 100644
index 00000000000..11fd98223eb
--- /dev/null
+++ b/microbenchmark-template/src/test/java/org/sonar/microbenchmark/SerializationBenchmarkTest.java
@@ -0,0 +1,77 @@
+package org.sonar.microbenchmark;
+
+import org.apache.commons.io.FileUtils;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.util.zip.Deflater;
+
+public class SerializationBenchmarkTest {
+
+ SerializationBenchmark benchmark = new SerializationBenchmark();
+
+ @Before
+ public void setUp() throws Exception {
+ benchmark.setup();
+ }
+
+ @Test
+ public void size_of_gson_output() throws Exception {
+ benchmark.write_gson();
+ System.out.println("GSON: " + sizeOf(benchmark.outputFile));
+ System.out.println("GSON (zipped): " + sizeOf(zipFile(benchmark.outputFile)));
+ }
+
+ @Test
+ public void size_of_protobuf_output() throws Exception {
+ benchmark.write_protobuf();
+ System.out.println("Protocol Buffers: " + sizeOf(benchmark.outputFile));
+ System.out.println("Protocol Buffers (zipped): " + sizeOf(zipFile(benchmark.outputFile)));
+ }
+
+ @Test
+ public void size_of_serializable_output() throws Exception {
+ benchmark.write_serializable();
+ System.out.println("java.io.Serializable: " + sizeOf(benchmark.outputFile));
+ System.out.println("java.io.Serializable (zipped): " + sizeOf(zipFile(benchmark.outputFile)));
+ }
+
+ @Test
+ public void size_of_externalizable_output() throws Exception {
+ benchmark.write_externalizable();
+ System.out.println("java.io.Externalizable: " + sizeOf(benchmark.outputFile));
+ System.out.println("java.io.Externalizable (zipped): " + sizeOf(zipFile(benchmark.outputFile)));
+ }
+
+ @Test
+ public void size_of_kryo_output() throws Exception {
+ benchmark.write_kryo();
+ System.out.println("Kryo: " + sizeOf(benchmark.outputFile));
+ System.out.println("Kryo (zipped): " + sizeOf(zipFile(benchmark.outputFile)));
+ }
+
+ private String sizeOf(File file) {
+ return FileUtils.byteCountToDisplaySize(FileUtils.sizeOf(file));
+ }
+
+ private File zipFile(File input) throws Exception {
+ File zipFile = new File(input.getAbsolutePath() + ".zip");
+ Deflater deflater = new Deflater();
+ byte[] content = FileUtils.readFileToByteArray(input);
+ deflater.setInput(content);
+ OutputStream outputStream = new FileOutputStream(zipFile);
+ deflater.finish();
+ byte[] buffer = new byte[1024];
+ while (!deflater.finished()) {
+ int count = deflater.deflate(buffer); // returns the generated code... index
+ outputStream.write(buffer, 0, count);
+ }
+ outputStream.close();
+ deflater.end();
+
+ return zipFile;
+ }
+}