changeset 0:d29e8a60f371

Initial commit for jmh-based Google Gson benchmark.
author Severin Gehwolf <sgehwolf@redhat.com>
date Wed, 26 Nov 2014 19:14:12 +0100
parents
children 7e72850203e2
files .hgignore pom.xml src/main/java/org/sample/GsonBenchmark.java src/main/java/org/sample/TestGsonBenchmark.java src/main/java/org/sample/model/Foo.java src/main/java/org/sample/model/Moose.java src/main/java/org/sample/model/typeadapters/FooTypeAdapter.java src/main/java/org/sample/model/typeadapters/MooseAdapterFactory.java src/main/java/org/sample/model/typeadapters/MooseTypeAdapter.java
diffstat 9 files changed, 453 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.hgignore	Wed Nov 26 19:14:12 2014 +0100
@@ -0,0 +1,3 @@
+target
+.classpath
+.settings
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pom.xml	Wed Nov 26 19:14:12 2014 +0100
@@ -0,0 +1,157 @@
+<!--
+Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code 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 General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+-->
+
+<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>
+
+    <groupId>org.sample</groupId>
+    <artifactId>test</artifactId>
+    <version>1.0</version>
+    <packaging>jar</packaging>
+
+    <name>Auto-generated JMH benchmark</name>
+
+    <prerequisites>
+        <maven>3.0</maven>
+    </prerequisites>
+
+    <dependencies>
+        <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>com.google.code.gson</groupId>
+      		<artifactId>gson</artifactId>
+      		<version>2.2.2</version>
+    	</dependency>
+    </dependencies>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <jmh.version>1.3.1</jmh.version>
+        <javac.target>1.6</javac.target>
+        <uberjar.name>benchmarks</uberjar.name>
+    </properties>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.1</version>
+                <configuration>
+                    <compilerVersion>${javac.target}</compilerVersion>
+                    <source>${javac.target}</source>
+                    <target>${javac.target}</target>
+                </configuration>
+            </plugin>
+            <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>
+                            <filters>
+                                <filter>
+                                    <!--
+                                        Shading signed JARs will fail without this.
+                                        http://stackoverflow.com/questions/999489/invalid-signature-file-when-attempting-to-run-a-jar
+                                    -->
+                                    <artifact>*:*</artifact>
+                                    <excludes>
+                                        <exclude>META-INF/*.SF</exclude>
+                                        <exclude>META-INF/*.DSA</exclude>
+                                        <exclude>META-INF/*.RSA</exclude>
+                                    </excludes>
+                                </filter>
+                            </filters>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+        <pluginManagement>
+            <plugins>
+                <plugin>
+                    <artifactId>maven-clean-plugin</artifactId>
+                    <version>2.5</version>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-deploy-plugin</artifactId>
+                    <version>2.8.1</version>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-install-plugin</artifactId>
+                    <version>2.5.1</version>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-jar-plugin</artifactId>
+                    <version>2.4</version>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-javadoc-plugin</artifactId>
+                    <version>2.9.1</version>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-resources-plugin</artifactId>
+                    <version>2.6</version>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-site-plugin</artifactId>
+                    <version>3.3</version>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-source-plugin</artifactId>
+                    <version>2.2.1</version>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-surefire-plugin</artifactId>
+                    <version>2.17</version>
+                </plugin>
+            </plugins>
+        </pluginManagement>
+    </build>
+
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/org/sample/GsonBenchmark.java	Wed Nov 26 19:14:12 2014 +0100
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.sample;
+
+import java.util.UUID;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.State;
+import org.sample.model.Foo;
+import org.sample.model.Moose;
+import org.sample.model.typeadapters.MooseAdapterFactory;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+public class GsonBenchmark {
+	
+	public static class Debuggable {
+		
+		protected final boolean debug;
+		
+		public Debuggable(boolean debug) {
+			this.debug = debug;
+		}
+	}
+	
+	@State(Scope.Thread)
+	public static class GsonStateTypeAdapter extends Debuggable {
+		
+		private Gson g = new GsonBuilder().registerTypeAdapterFactory(new MooseAdapterFactory()).create();
+		private UUID uuid = UUID.randomUUID();
+		private int count;
+
+		public GsonStateTypeAdapter() {
+			super(false);
+		}
+		
+		GsonStateTypeAdapter(boolean debug) {
+			super(debug);
+		}
+	}
+	
+	@State(Scope.Thread)
+	public static class GsonStateNoTypeAdapter extends Debuggable {
+		private Gson g = new GsonBuilder().create();
+		private UUID uuid = UUID.randomUUID();
+		private int count;
+		
+		public GsonStateNoTypeAdapter() {
+			super(false);
+		}
+		
+		GsonStateNoTypeAdapter(boolean debug) {
+			super(debug);
+		}
+	}
+	
+	/**
+	 * Benchmark gson serialization and deserialization
+	 * with a Gson that has the custom type adapter registered.
+	 * 
+	 * @param state
+	 */
+    @Benchmark
+    public void benchmarkNoTypeAdapter(GsonStateNoTypeAdapter state) {
+    	Moose moose = new Moose(new Foo(state.uuid), state.count++);
+    	String jsonString = state.g.toJson(moose);
+    	if (state.debug) {
+    		System.out.println(jsonString);
+    	}
+    	Moose otherMoose = state.g.fromJson(jsonString, Moose.class);
+    	if (state.debug) {
+    		System.out.println("count: " + otherMoose.getCount() + ", UUID: " + otherMoose.getFoo().getUuid());
+    	}
+    }
+    
+    /**
+     * Benchmark gson serialization and deserialization
+	 * with a Gson that has <strong>no</strong> type adapter registered.
+	 * 
+     * @param state
+     */
+    @Benchmark
+    public void benchmarkWithTypeAdapter(GsonStateTypeAdapter state) {
+    	Moose moose = new Moose(new Foo(state.uuid), state.count++);
+    	String jsonString = state.g.toJson(moose);
+    	if (state.debug) {
+    		System.out.println(jsonString);
+    	}
+    	Moose otherMoose = state.g.fromJson(jsonString, Moose.class);
+    	if (state.debug) {
+    		System.out.println("count: " + otherMoose.getCount() + ", UUID: " + otherMoose.getFoo().getUuid());
+    	}
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/org/sample/TestGsonBenchmark.java	Wed Nov 26 19:14:12 2014 +0100
@@ -0,0 +1,18 @@
+package org.sample;
+
+import org.sample.GsonBenchmark.GsonStateNoTypeAdapter;
+import org.sample.GsonBenchmark.GsonStateTypeAdapter;
+
+public class TestGsonBenchmark {
+
+	public static void main(String[] args) {
+		GsonBenchmark bench = new GsonBenchmark();
+		GsonStateTypeAdapter typeAdapterState = new GsonStateTypeAdapter(true);
+		GsonStateNoTypeAdapter noTypeAdapterState = new GsonStateNoTypeAdapter(true);
+		bench.benchmarkWithTypeAdapter(typeAdapterState);
+		bench.benchmarkWithTypeAdapter(typeAdapterState);
+		bench.benchmarkNoTypeAdapter(noTypeAdapterState);
+		bench.benchmarkNoTypeAdapter(noTypeAdapterState);
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/org/sample/model/Foo.java	Wed Nov 26 19:14:12 2014 +0100
@@ -0,0 +1,17 @@
+package org.sample.model;
+
+import java.util.UUID;
+
+public class Foo {
+
+	private final UUID uuuu;
+	
+	public Foo(UUID uuid) {
+		this.uuuu = uuid;
+	}
+
+	public UUID getUuid() {
+		return uuuu;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/org/sample/model/Moose.java	Wed Nov 26 19:14:12 2014 +0100
@@ -0,0 +1,21 @@
+package org.sample.model;
+
+public class Moose {
+
+	private final int ccccc;
+	private final Foo fff;
+	
+	public Moose(Foo foo, int count) {
+		this.fff = foo;
+		this.ccccc = count;
+	}
+	
+	public int getCount() {
+		return ccccc;
+	}
+
+	public Foo getFoo() {
+		return fff;
+	}
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/org/sample/model/typeadapters/FooTypeAdapter.java	Wed Nov 26 19:14:12 2014 +0100
@@ -0,0 +1,41 @@
+package org.sample.model.typeadapters;
+
+import java.io.IOException;
+import java.util.UUID;
+
+import org.sample.model.Foo;
+
+import com.google.gson.TypeAdapter;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
+import com.google.gson.stream.JsonWriter;
+
+public class FooTypeAdapter extends TypeAdapter<Foo> {
+
+	@Override
+	public void write(JsonWriter out, Foo value) throws IOException {
+		if (value == null) {
+			out.nullValue();
+			return;
+		}
+		out.beginObject();
+		out.name("uuid");
+		out.value(value.getUuid().toString());
+		out.endObject();
+	}
+
+	@Override
+	public Foo read(JsonReader in) throws IOException {
+		if (in.peek() == JsonToken.NULL) {
+			in.nextNull();
+			return null;
+		}
+		in.beginObject();
+		in.nextName();
+		String uuid = in.nextString();
+		UUID u = UUID.fromString(uuid);
+		in.endObject();
+		return new Foo(u);
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/org/sample/model/typeadapters/MooseAdapterFactory.java	Wed Nov 26 19:14:12 2014 +0100
@@ -0,0 +1,25 @@
+package org.sample.model.typeadapters;
+
+import org.sample.model.Foo;
+import org.sample.model.Moose;
+
+import com.google.gson.Gson;
+import com.google.gson.TypeAdapter;
+import com.google.gson.TypeAdapterFactory;
+import com.google.gson.reflect.TypeToken;
+
+public class MooseAdapterFactory implements TypeAdapterFactory {
+
+	@Override
+	public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
+		Class<?> rawType = type.getRawType();
+        if (rawType == Moose.class) {
+        	TypeAdapter<Foo> fooAdapter = new FooTypeAdapter();
+            @SuppressWarnings("unchecked")
+            TypeAdapter<T> ta = (TypeAdapter<T>)new MooseTypeAdapter(fooAdapter);
+            return ta;
+        }
+        return null;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/org/sample/model/typeadapters/MooseTypeAdapter.java	Wed Nov 26 19:14:12 2014 +0100
@@ -0,0 +1,51 @@
+package org.sample.model.typeadapters;
+
+import java.io.IOException;
+
+import org.sample.model.Foo;
+import org.sample.model.Moose;
+
+import com.google.gson.TypeAdapter;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
+import com.google.gson.stream.JsonWriter;
+
+public class MooseTypeAdapter extends TypeAdapter<Moose> {
+
+	private final TypeAdapter<Foo> fooAdapter;
+	
+	public MooseTypeAdapter(TypeAdapter<Foo> fooAdapter) {
+		this.fooAdapter = fooAdapter;
+	}
+	
+	@Override
+	public void write(JsonWriter out, Moose value) throws IOException {
+		if (value == null) {
+			out.nullValue();
+			return;
+		}
+		out.beginObject();
+		out.name("count");
+		out.value(value.getCount());
+		out.name("foo");
+		fooAdapter.write(out, value.getFoo());
+		out.endObject();
+	}
+
+	@Override
+	public Moose read(JsonReader in) throws IOException {
+		if (in.peek() == JsonToken.NULL) {
+			in.nextNull();
+			return null;
+		}
+		in.beginObject();
+		in.nextName();
+		int count = in.nextInt();
+		in.nextName();
+		Foo foo = fooAdapter.read(in);
+		in.endObject();
+		
+		return new Moose(foo, count);
+	}
+
+}