Przeglądaj źródła

Merge pull request #4014 from BSBandme/JavaCaliper

Add caliper supported to java benchmark
Yilun Chong 7 lat temu
rodzic
commit
43caa38d6e

+ 25 - 12
benchmarks/Makefile.am

@@ -20,7 +20,7 @@ benchmarks_protoc_inputs_proto2 =                                          \
 	datasets/google_message4/benchmark_message4_3.proto
 	datasets/google_message4/benchmark_message4_3.proto
 
 
 make_tmp_dir:
 make_tmp_dir:
-	mkdir -p 'tmp'
+	mkdir -p 'tmp/java/src/main/java'
 	touch make_tmp_dir
 	touch make_tmp_dir
 
 
 if USE_EXTERNAL_PROTOC
 if USE_EXTERNAL_PROTOC
@@ -39,11 +39,11 @@ else
 # relative to srcdir, which may not be the same as the current directory when
 # relative to srcdir, which may not be the same as the current directory when
 # building out-of-tree.
 # building out-of-tree.
 protoc_middleman: make_tmp_dir $(top_srcdir)/src/protoc$(EXEEXT) $(benchmarks_protoc_inputs) $(well_known_type_protoc_inputs)
 protoc_middleman: make_tmp_dir $(top_srcdir)/src/protoc$(EXEEXT) $(benchmarks_protoc_inputs) $(well_known_type_protoc_inputs)
-	oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd --java_out=$$oldpwd/tmp $(benchmarks_protoc_inputs) )
+	oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd --java_out=$$oldpwd/tmp/java/src/main/java $(benchmarks_protoc_inputs) )
 	touch protoc_middleman
 	touch protoc_middleman
 
 
 protoc_middleman2:  make_tmp_dir $(top_srcdir)/src/protoc$(EXEEXT) $(benchmarks_protoc_inputs_proto2) $(well_known_type_protoc_inputs)
 protoc_middleman2:  make_tmp_dir $(top_srcdir)/src/protoc$(EXEEXT) $(benchmarks_protoc_inputs_proto2) $(well_known_type_protoc_inputs)
-	oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd --java_out=$$oldpwd/tmp $(benchmarks_protoc_inputs_proto2) )
+	oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd --java_out=$$oldpwd/tmp/java/src/main/java $(benchmarks_protoc_inputs_proto2) )
 	touch protoc_middleman2
 	touch protoc_middleman2
 	
 	
 endif
 endif
@@ -100,6 +100,17 @@ $(benchmarks_protoc_outputs_header): protoc_middleman
 $(benchmarks_protoc_outputs_proto2): protoc_middleman2
 $(benchmarks_protoc_outputs_proto2): protoc_middleman2
 $(benchmarks_protoc_outputs_proto2_header): protoc_middleman2
 $(benchmarks_protoc_outputs_proto2_header): protoc_middleman2
 
 
+initialize_submodule:
+	oldpwd=`pwd`
+	cd $(top_srcdir)/third_party
+	git submodule update --init -r
+	cd $(top_srcdir)/third_party/benchmark && cmake -DCMAKE_BUILD_TYPE=Release && make
+	cd $$oldpwd
+	touch initialize_submodule
+	
+$(top_srcdir)/src/libprotobuf.la: initialize_submodule
+$(top_srcdir)/third_party/benchmark/src/libbenchmark.a: initialize_submodule
+
 AM_CXXFLAGS = $(NO_OPT_CXXFLAGS) $(PROTOBUF_OPT_FLAG) -Wall -Wwrite-strings -Woverloaded-virtual -Wno-sign-compare
 AM_CXXFLAGS = $(NO_OPT_CXXFLAGS) $(PROTOBUF_OPT_FLAG) -Wall -Wwrite-strings -Woverloaded-virtual -Wno-sign-compare
 
 
 bin_PROGRAMS = cpp-benchmark
 bin_PROGRAMS = cpp-benchmark
@@ -110,32 +121,33 @@ cpp_benchmark_CPPFLAGS = -I$(top_srcdir)/src -I$(srcdir) -I$(top_srcdir)/third_p
 # Explicit deps because BUILT_SOURCES are only done before a "make all/check"
 # Explicit deps because BUILT_SOURCES are only done before a "make all/check"
 # so a direct "make test_cpp" could fail if parallel enough.
 # so a direct "make test_cpp" could fail if parallel enough.
 # See: https://www.gnu.org/software/automake/manual/html_node/Built-Sources-Example.html#Recording-Dependencies-manually
 # See: https://www.gnu.org/software/automake/manual/html_node/Built-Sources-Example.html#Recording-Dependencies-manually
-cpp_benchmark-cpp_benchmark.$(OBJEXT): $(benchmarks_protoc_outputs) $(benchmarks_protoc_outputs_proto2) $(benchmarks_protoc_outputs_header) $(benchmarks_protoc_outputs_proto2_header)
+cpp_benchmark-cpp_benchmark.$(OBJEXT): $(benchmarks_protoc_outputs) $(benchmarks_protoc_outputs_proto2) $(benchmarks_protoc_outputs_header) $(benchmarks_protoc_outputs_proto2_header) $(top_srcdir)/src/libprotobuf.la $(top_srcdir)/third_party/benchmark/src/libbenchmark.a
 nodist_cpp_benchmark_SOURCES =                                             \
 nodist_cpp_benchmark_SOURCES =                                             \
 	$(benchmarks_protoc_outputs)                                             \
 	$(benchmarks_protoc_outputs)                                             \
 	$(benchmarks_protoc_outputs_proto2)                                      \
 	$(benchmarks_protoc_outputs_proto2)                                      \
 	$(benchmarks_protoc_outputs_proto2_header)                               \
 	$(benchmarks_protoc_outputs_proto2_header)                               \
 	$(benchmarks_protoc_outputs_header)
 	$(benchmarks_protoc_outputs_header)
 
 
-cpp: protoc_middleman protoc_middleman2 cpp-benchmark
+cpp: protoc_middleman protoc_middleman2 cpp-benchmark initialize_submodule
 	./cpp-benchmark $(all_data)
 	./cpp-benchmark $(all_data)
 
 
 ############ CPP RULES END ############
 ############ CPP RULES END ############
 
 
 ############# JAVA RULES ##############
 ############# JAVA RULES ##############
 
 
-javac_middleman: ProtoBench.java protoc_middleman protoc_middleman2
-	jar=`ls $(top_srcdir)/java/util/target/*.jar` &&                         \
-	jar1=`ls $(top_srcdir)/java/core/target/*.jar` &&                        \
-	javac -d tmp -classpath ../java/target/classes:$$jar:$$jar1 ProtoBench.java $(benchmark_java_protoc_outputs_proto2) $(benchmarks_java_protoc_outputs) `find tmp -type f -name "*.java"`
+java_benchmark_testing_files =                                      \
+	java/src/main/java/com/google/protobuf/ProtoBench.java            \
+	java/src/main/java/com/google/protobuf/ProtoBenchCaliper.java
+
+javac_middleman: $(java_benchmark_testing_files) protoc_middleman protoc_middleman2
+	cp -r java tmp && cd tmp/java &&  mvn clean compile assembly:single
+	cd ../..
 	@touch javac_middleman
 	@touch javac_middleman
 
 
 java-benchmark: javac_middleman 
 java-benchmark: javac_middleman 
 	@echo "Writing shortcut script java-benchmark..."
 	@echo "Writing shortcut script java-benchmark..."
 	@echo '#! /bin/sh' > java-benchmark
 	@echo '#! /bin/sh' > java-benchmark
-	@jar=`ls $(top_srcdir)/java/util/target/*.jar` &&                        \
-	jar1=`ls $(top_srcdir)/java/core/target/*.jar` &&                        \
-	echo java -classpath tmp:../java/target/classes:$$jar:$$jar1 com.google.protocolbuffers.ProtoBench '$$@' >> java-benchmark
+	@echo 'java -cp '"tmp/java/target/*.jar"' com.google.protobuf.ProtoBench $$@' >> java-benchmark
 	@chmod +x java-benchmark
 	@chmod +x java-benchmark
 
 
 java: protoc_middleman protoc_middleman2 java-benchmark
 java: protoc_middleman protoc_middleman2 java-benchmark
@@ -151,6 +163,7 @@ CLEANFILES =                                                               \
 	$(benchmarks_protoc_outputs_header)                                      \
 	$(benchmarks_protoc_outputs_header)                                      \
 	$(benchmarks_protoc_outputs_proto2)                                      \
 	$(benchmarks_protoc_outputs_proto2)                                      \
 	$(benchmarks_protoc_outputs_proto2_header)                               \
 	$(benchmarks_protoc_outputs_proto2_header)                               \
+	initialize_submodule                                                     \
 	make_tmp_dir                                                             \
 	make_tmp_dir                                                             \
 	protoc_middleman                                                         \
 	protoc_middleman                                                         \
 	protoc_middleman2                                                        \
 	protoc_middleman2                                                        \

+ 0 - 319
benchmarks/ProtoBench.java

@@ -1,319 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2009 Google Inc.  All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package com.google.protocolbuffers;
-
-import com.google.protobuf.ByteString;
-import com.google.protobuf.CodedInputStream;
-import com.google.protobuf.CodedOutputStream;
-import com.google.protobuf.ExtensionRegistry;
-import com.google.protobuf.Message;
-import com.google.protobuf.benchmarks.Benchmarks.BenchmarkDataset;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.util.ArrayList;
-import java.util.List;
-
-public class ProtoBench {
-
-  private static final long MIN_SAMPLE_TIME_MS = 1 * 1000;
-  private static final long TARGET_TIME_MS = 5 * 1000;
-
-  private ProtoBench() {
-    // Prevent instantiation
-  }
-  
-  public static void main(String[] args) {
-    if (args.length < 1) {
-      System.err.println("Usage: ./java-benchmark <input data>");
-      System.err.println("input data is in the format of \"benchmarks.proto\"");
-      System.exit(1);
-    }
-    boolean success = true;
-    for (int i = 0; i < args.length; i++) {
-      success &= runTest(args[i]);
-    }
-    System.exit(success ? 0 : 1);
-  }
-  
-  public static ExtensionRegistry getExtensionsRegistry(BenchmarkDataset benchmarkDataset) {
-    ExtensionRegistry extensions = ExtensionRegistry.newInstance();
-    if (benchmarkDataset.getMessageName().equals("benchmarks.google_message3.GoogleMessage3")) {
-      benchmarks.google_message3.BenchmarkMessage38.registerAllExtensions(extensions);
-      benchmarks.google_message3.BenchmarkMessage37.registerAllExtensions(extensions);
-      benchmarks.google_message3.BenchmarkMessage36.registerAllExtensions(extensions);
-      benchmarks.google_message3.BenchmarkMessage35.registerAllExtensions(extensions);
-      benchmarks.google_message3.BenchmarkMessage34.registerAllExtensions(extensions);
-      benchmarks.google_message3.BenchmarkMessage33.registerAllExtensions(extensions);
-      benchmarks.google_message3.BenchmarkMessage32.registerAllExtensions(extensions);
-      benchmarks.google_message3.BenchmarkMessage31.registerAllExtensions(extensions);
-      benchmarks.google_message3.BenchmarkMessage3.registerAllExtensions(extensions);
-    } else if (benchmarkDataset.getMessageName().equals(
-        "benchmarks.google_message4.GoogleMessage4")) {
-      benchmarks.google_message4.BenchmarkMessage43.registerAllExtensions(extensions);
-      benchmarks.google_message4.BenchmarkMessage42.registerAllExtensions(extensions);
-      benchmarks.google_message4.BenchmarkMessage41.registerAllExtensions(extensions);
-      benchmarks.google_message4.BenchmarkMessage4.registerAllExtensions(extensions);      
-    }
-    
-    return extensions;
-  }
-
-  /**
-   * Return an message instance for one specific dataset, and register the extensions for that 
-   * message. 
-   */
-  public static Message registerBenchmarks(BenchmarkDataset benchmarkDataset) {
-    if (benchmarkDataset.getMessageName().equals("benchmarks.proto3.GoogleMessage1")) {
-      return com.google.protobuf.benchmarks.BenchmarkMessage1Proto3.GoogleMessage1
-          .getDefaultInstance();
-    } else if (benchmarkDataset.getMessageName().equals("benchmarks.proto2.GoogleMessage1")) {
-      return com.google.protobuf.benchmarks.BenchmarkMessage1Proto2.GoogleMessage1
-          .getDefaultInstance();
-    } else if (benchmarkDataset.getMessageName().equals("benchmarks.proto2.GoogleMessage2")) {
-      return com.google.protobuf.benchmarks.BenchmarkMessage2.GoogleMessage2.getDefaultInstance();
-    } else if (benchmarkDataset.getMessageName().
-        equals("benchmarks.google_message3.GoogleMessage3")) {
-      return benchmarks.google_message3.BenchmarkMessage3.GoogleMessage3.getDefaultInstance();
-    } else if (benchmarkDataset.getMessageName().
-        equals("benchmarks.google_message4.GoogleMessage4")) {
-      return benchmarks.google_message4.BenchmarkMessage4.GoogleMessage4.getDefaultInstance();
-    } else {
-      return null;
-    }
-  }
-
-  /**
-   * Runs a single test. Error messages are displayed to stderr, and the return value indicates
-   * general success/failure.
-   */
-  public static boolean runTest(String file) {
-    final Message defaultMessage;
-    BenchmarkDataset benchmarkDataset;
-    ExtensionRegistry extensions;
-    final byte[] inputData;
-
-    try {
-      inputData = readAllBytes(file);
-      benchmarkDataset = BenchmarkDataset.parseFrom(inputData);
-    } catch (IOException e) {
-      System.err.println("Unable to get input data");
-      return false;
-    }
-    defaultMessage = registerBenchmarks(benchmarkDataset);
-    extensions = getExtensionsRegistry(benchmarkDataset);
-    if (defaultMessage == null) {
-      System.err.println("Unable to get default message " + benchmarkDataset.getMessageName());
-      return false;
-    }
-    System.out.println("Benchmarking " + benchmarkDataset.getMessageName() + " with file " + file);
-
-    try {
-      List<byte[]> inputDataList = new ArrayList<byte[]>();
-      List<ByteArrayInputStream> inputStreamList = new ArrayList<ByteArrayInputStream>();
-      List<ByteString> inputStringList = new ArrayList<ByteString>();
-      List<Message> sampleMessageList = new ArrayList<Message>();
-
-      for (int i = 0; i < benchmarkDataset.getPayloadCount(); i++) {
-        byte[] singleInputData = benchmarkDataset.getPayload(i).toByteArray();
-        inputDataList.add(benchmarkDataset.getPayload(i).toByteArray());
-        inputStreamList.add(new ByteArrayInputStream(benchmarkDataset.getPayload(i).toByteArray()));
-        inputStringList.add(benchmarkDataset.getPayload(i));
-        sampleMessageList.add(
-            defaultMessage.newBuilderForType().mergeFrom(singleInputData, extensions).build());
-      }
-
-      FileOutputStream devNullTemp = null;
-      CodedOutputStream reuseDevNullTemp = null;
-      try {
-        devNullTemp = new FileOutputStream("/dev/null");
-        reuseDevNullTemp = CodedOutputStream.newInstance(devNullTemp);
-      } catch (FileNotFoundException e) {
-        // ignore: this is probably Windows, where /dev/null does not exist
-      }
-      final FileOutputStream devNull = devNullTemp;
-      final CodedOutputStream reuseDevNull = reuseDevNullTemp;
-      benchmark(
-          "Serialize to byte string",
-          inputData.length,
-          new Action() {
-            public void execute() {
-              for (int i = 0; i < sampleMessageList.size(); i++) {
-                sampleMessageList.get(i).toByteString();
-              }
-            }
-          });
-      benchmark(
-          "Serialize to byte array",
-          inputData.length,
-          new Action() {
-            public void execute() {
-              for (int i = 0; i < sampleMessageList.size(); i++) {
-                sampleMessageList.get(i).toByteString();
-              }
-            }
-          });
-      benchmark(
-          "Serialize to memory stream",
-          inputData.length,
-          new Action() {
-            public void execute() throws IOException {
-              ByteArrayOutputStream output = new ByteArrayOutputStream();
-              for (int i = 0; i < sampleMessageList.size(); i++) {
-                sampleMessageList.get(i).writeTo(output);
-              }
-            }
-          });
-      if (devNull != null) {
-        benchmark(
-            "Serialize to /dev/null with FileOutputStream",
-            inputData.length,
-            new Action() {
-              public void execute() throws IOException {
-                for (int i = 0; i < sampleMessageList.size(); i++) {
-                  sampleMessageList.get(i).writeTo(devNull);
-                }
-              }
-            });
-        benchmark(
-            "Serialize to /dev/null reusing FileOutputStream",
-            inputData.length,
-            new Action() {
-              public void execute() throws IOException {
-                for (int i = 0; i < sampleMessageList.size(); i++) {
-                  sampleMessageList.get(i).writeTo(reuseDevNull);
-                  reuseDevNull.flush(); // force the write to the OutputStream
-                }
-              }
-            });
-      }
-      benchmark(
-          "Deserialize from byte string",
-          inputData.length,
-          new Action() {
-            public void execute() throws IOException {
-              for (int i = 0; i < inputStringList.size(); i++) {
-                defaultMessage
-                    .newBuilderForType()
-                    .mergeFrom(inputStringList.get(i), extensions)
-                    .build();
-              }
-            }
-          });
-      benchmark(
-          "Deserialize from byte array",
-          inputData.length,
-          new Action() {
-            public void execute() throws IOException {
-              for (int i = 0; i < inputDataList.size(); i++) {
-                defaultMessage
-                    .newBuilderForType()
-                    .mergeFrom(CodedInputStream.newInstance(inputDataList.get(i)), extensions)
-                    .build();
-              }
-            }
-          });
-      benchmark(
-          "Deserialize from memory stream",
-          inputData.length,
-          new Action() {
-            public void execute() throws IOException {
-              for (int i = 0; i < inputStreamList.size(); i++) {
-                defaultMessage
-                    .newBuilderForType()
-                    .mergeFrom(CodedInputStream.newInstance(inputStreamList.get(i)), extensions)
-                    .build();
-                inputStreamList.get(i).reset();
-              }
-            }
-          });
-      System.out.println();
-      return true;
-    } catch (Exception e) {
-      System.err.println("Error: " + e.getMessage());
-      System.err.println("Detailed exception information:");
-      e.printStackTrace(System.err);
-      return false;
-    }
-  }
-  
-  private static void benchmark(String name, long dataSize, Action action) throws IOException {
-    // Make sure it's JITted "reasonably" hard before running the first progress test
-    for (int i=0; i < 100; i++) {
-      action.execute();
-    }
-    
-    // Run it progressively more times until we've got a reasonable sample
-    int iterations = 1;
-    long elapsed = timeAction(action, iterations);
-    while (elapsed < MIN_SAMPLE_TIME_MS) {
-      iterations *= 2;
-      elapsed = timeAction(action, iterations);
-    }
-    
-    // Upscale the sample to the target time. Do this in floating point arithmetic
-    // to avoid overflow issues.
-    iterations = (int) ((TARGET_TIME_MS / (double) elapsed) * iterations);
-    elapsed = timeAction(action, iterations);
-    System.out.println(name + ": " + iterations + " iterations in "
-         + (elapsed/1000f) + "s; " 
-         + (iterations * dataSize) / (elapsed * 1024 * 1024 / 1000f) 
-         + "MB/s");
-  }
-  
-  private static long timeAction(Action action, int iterations) throws IOException {
-    System.gc();    
-    long start = System.currentTimeMillis();
-    for (int i = 0; i < iterations; i++) {
-      action.execute();
-    }
-    long end = System.currentTimeMillis();
-    return end - start;
-  }
-  
-  private static byte[] readAllBytes(String filename) throws IOException {
-    RandomAccessFile file = new RandomAccessFile(new File(filename), "r");
-    byte[] content = new byte[(int) file.length()];
-    file.readFully(content);
-    return content;
-  }
-
-  /**
-   * Interface used to capture a single action to benchmark.
-   */
-  interface Action {
-    void execute() throws IOException;
-  }
-}

+ 38 - 4
benchmarks/README.md

@@ -5,7 +5,36 @@ This directory contains benchmarking schemas and data sets that you
 can use to test a variety of performance scenarios against your
 can use to test a variety of performance scenarios against your
 protobuf language runtime.
 protobuf language runtime.
 
 
-The schema for the datasets is described in `benchmarks.proto`.
+## Prerequisite
+
+First, you need to follow the instruction in the root directory's README to 
+build your language's protobuf, then:
+
+### CPP
+You need to install [cmake](https://cmake.org/) before building the benchmark.
+
+We are using [google/benchmark](https://github.com/google/benchmark) as the 
+benchmark tool for testing cpp. This will be automaticly made during build the 
+cpp benchmark.
+
+### JAVA
+We're using maven to build the java benchmarks, which is the same as to build 
+the Java protobuf. There're no other tools need to install. We're using 
+[google/caliper](https://github.com/google/caliper) as benchmark tool, which 
+can be automaticly included by maven.
+
+### Big data
+
+There's some optional big testing data which is not included in the directory initially, you need to 
+run the following command to download the testing data:
+
+```
+$ ./download_data.sh 
+```
+
+After doing this the big data file will automaticly generated in the benchmark directory.  
+
+## Run instructions
 
 
 To run all the benchmark dataset:
 To run all the benchmark dataset:
 
 
@@ -26,22 +55,27 @@ To run a specific dataset:
 For java:
 For java:
 
 
 ```
 ```
-$ make java
-$ ./java-benchmark $(specific generated dataset file name)
+$ make java-benchmark
+$ ./java-benchmark $(specific generated dataset file name) [-- $(caliper option)]
 ```
 ```
 
 
 For cpp:
 For cpp:
 
 
 ```
 ```
-$ make cpp
+$ make cpp-benchmark
 $ ./cpp-benchmark $(specific generated dataset file name)
 $ ./cpp-benchmark $(specific generated dataset file name)
 ```
 ```
 
 
+## Benchmark datasets
+
 Each data set is in the format of benchmarks.proto:
 Each data set is in the format of benchmarks.proto:
+
 1. name is the benchmark dataset's name.
 1. name is the benchmark dataset's name.
 2. message_name is the benchmark's message type full name (including package and message name)
 2. message_name is the benchmark's message type full name (including package and message name)
 3. payload is the list of raw data.
 3. payload is the list of raw data.
 
 
+The schema for the datasets is described in `benchmarks.proto`.
+
 Benchmark likely want to run several benchmarks against each data set (parse,
 Benchmark likely want to run several benchmarks against each data set (parse,
 serialize, possibly JSON, possibly using different APIs, etc).
 serialize, possibly JSON, possibly using different APIs, etc).
 
 

+ 95 - 0
benchmarks/java/pom.xml

@@ -0,0 +1,95 @@
+<?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/maven-v4_0_0.xsd">
+  
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>protobuf-java-benchmark</artifactId>
+  <groupId>com.google.protobuf</groupId>
+  <version>1.0.0</version>
+  <name>Protocol Buffers [Benchmark]</name>
+  <description>The benchmark tools for Protobuf Java.</description>
+  
+  <dependencies>
+    <dependency>
+      <groupId>com.google.protobuf</groupId>
+      <artifactId>protobuf-java</artifactId>
+      <version>3.5.0</version>
+    </dependency>
+    <dependency>
+      <groupId>com.google.caliper</groupId>
+      <artifactId>caliper</artifactId>
+      <version>1.0-beta-2</version>
+    </dependency>
+  </dependencies>
+  
+  <build>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-assembly-plugin</artifactId>
+          <version>2.4.1</version>
+          <configuration>
+            <!-- get all project dependencies -->
+            <descriptorRefs>
+              <descriptorRef>jar-with-dependencies</descriptorRef>
+            </descriptorRefs>
+            <!-- MainClass in mainfest make a executable jar -->
+            <archive>
+              <manifest>
+                <mainClass>com.mkyong.core.utils.App</mainClass>
+              </manifest>
+            </archive>
+          </configuration>
+          <executions>
+            <execution>
+              <id>make-assembly</id>
+              <!-- bind to the packaging phase -->
+              <phase>package</phase>
+              <goals>
+                <goal>single</goal>
+              </goals>
+            </execution>
+          </executions>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-compiler-plugin</artifactId>
+          <version>3.5.1</version>
+          <configuration>
+            <source>1.8</source>
+            <target>1.8</target>
+          </configuration>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-jar-plugin</artifactId>
+          <version>2.5</version>
+          <configuration>
+            <archive>
+              <manifest>
+                <addClasspath>true</addClasspath>
+                <mainClass>com.google.protocolbuffers.ProtoBench</mainClass>
+              </manifest>
+            </archive>
+          </configuration>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-source-plugin</artifactId>
+          <version>2.4</version>
+          <executions>
+            <execution>
+              <id>attach-sources</id>
+              <goals>
+                <goal>jar-no-fork</goal>
+              </goals>
+            </execution>
+          </executions>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+  </build>
+</project>
+

+ 148 - 0
benchmarks/java/src/main/java/com/google/protobuf/ProtoBench.java

@@ -0,0 +1,148 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2009 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+package com.google.protobuf;
+
+import com.google.caliper.BeforeExperiment;
+import com.google.caliper.Benchmark;
+import com.google.caliper.Param;
+import com.google.caliper.runner.CaliperMain;
+import com.google.protobuf.ByteString;
+import com.google.protobuf.CodedInputStream;
+import com.google.protobuf.CodedOutputStream;
+import com.google.protobuf.ExtensionRegistry;
+import com.google.protobuf.Message;
+import com.google.protobuf.benchmarks.Benchmarks.BenchmarkDataset;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.RandomAccessFile;
+import java.util.ArrayList;
+import java.util.List;
+
+
+public class ProtoBench {
+
+  private ProtoBench() {
+    // Prevent instantiation
+  }
+    
+  public static void main(String[] args) {
+    if (args.length < 1) {
+      System.err.println("Usage: ./java-benchmark <input data>");
+      System.err.println("input data is in the format of \"benchmarks.proto\"");
+      System.exit(1);
+    }
+    boolean success = true;
+    for (int i = 0; i < args.length; i++) {
+      success &= runTest(args[i]);
+    }
+    System.exit(success ? 0 : 1);
+  }
+ 
+  /**
+   * Runs a single test with specific test data. Error messages are displayed to stderr, 
+   * and the return value indicates general success/failure.
+   */
+  public static boolean runTest(String file) {
+    byte[] inputData;
+    BenchmarkDataset benchmarkDataset;
+    try {
+      inputData = readAllBytes(file);
+      benchmarkDataset = BenchmarkDataset.parseFrom(inputData);
+    } catch (IOException e) {
+      System.err.println("Unable to get input data");
+      return false;
+    }
+    
+    List<String> argsList = getCaliperOption(benchmarkDataset);
+    if (argsList == null) {
+      System.err.println("Unable to get default message " + benchmarkDataset.getMessageName());
+      return false;
+    }
+    argsList.add("-DdataFile=" + file);
+    argsList.add("com.google.protobuf.ProtoBenchCaliper");
+    
+    try {
+      String args[] = new String[argsList.size()];
+      argsList.toArray(args);
+      CaliperMain.exitlessMain(args, 
+          new PrintWriter(System.out, true), new PrintWriter(System.err, true));
+      return true;
+    } catch (Exception e) {
+      System.err.println("Error: " + e.getMessage());
+      System.err.println("Detailed exception information:");
+      e.printStackTrace(System.err);
+      return false;
+    }
+  }
+  
+  
+  private static List<String> getCaliperOption(final BenchmarkDataset benchmarkDataset) {
+    List<String> temp = new ArrayList<String>();
+    if (benchmarkDataset.getMessageName().equals("benchmarks.proto3.GoogleMessage1")) {
+      temp.add("-DbenchmarkMessageType=GOOGLE_MESSAGE1_PROTO3");
+    } else if (benchmarkDataset.getMessageName().equals("benchmarks.proto2.GoogleMessage1")) {
+      temp.add("-DbenchmarkMessageType=GOOGLE_MESSAGE1_PROTO2");
+    } else if (benchmarkDataset.getMessageName().equals("benchmarks.proto2.GoogleMessage2")) {
+      temp.add("-DbenchmarkMessageType=GOOGLE_MESSAGE2");
+    } else if (benchmarkDataset.getMessageName().
+        equals("benchmarks.google_message3.GoogleMessage3")) {
+      temp.add("-DbenchmarkMessageType=GOOGLE_MESSAGE3");
+    } else if (benchmarkDataset.getMessageName().
+        equals("benchmarks.google_message4.GoogleMessage4")) {
+      temp.add("-DbenchmarkMessageType=GOOGLE_MESSAGE4");
+    } else {
+      return null;
+    }
+    
+    temp.add("-i");
+    temp.add("runtime");
+    temp.add("-b");
+    String benchmarkNames = "serializeToByteString,serializeToByteArray,serializeToMemoryStream"
+       + ",deserializeFromByteString,deserializeFromByteArray,deserializeFromMemoryStream";
+    temp.add(benchmarkNames);
+    temp.add("-Cinstrument.runtime.options.timingInterval=3000ms");
+    
+    return temp;
+  }
+  
+  public static byte[] readAllBytes(String filename) throws IOException {
+    RandomAccessFile file = new RandomAccessFile(new File(filename), "r");
+    byte[] content = new byte[(int) file.length()];
+    file.readFully(content);
+    return content;
+  }
+}

+ 183 - 0
benchmarks/java/src/main/java/com/google/protobuf/ProtoBenchCaliper.java

@@ -0,0 +1,183 @@
+
+package com.google.protobuf;
+
+import com.google.caliper.BeforeExperiment;
+import com.google.caliper.Benchmark;
+import com.google.caliper.Param;
+import com.google.protobuf.ByteString;
+import com.google.protobuf.CodedOutputStream;
+import com.google.protobuf.ExtensionRegistry;
+import com.google.protobuf.Message;
+import com.google.protobuf.benchmarks.Benchmarks.BenchmarkDataset;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class ProtoBenchCaliper {
+  public enum BenchmarkMessageType {
+    GOOGLE_MESSAGE1_PROTO3 {
+      @Override ExtensionRegistry getExtensionRegistry() { return ExtensionRegistry.newInstance(); }
+      @Override
+      Message getDefaultInstance() {
+        return com.google.protobuf.benchmarks.BenchmarkMessage1Proto3.GoogleMessage1
+            .getDefaultInstance();
+      }
+    },
+    GOOGLE_MESSAGE1_PROTO2 {
+      @Override ExtensionRegistry getExtensionRegistry() { return ExtensionRegistry.newInstance(); }
+      @Override
+      Message getDefaultInstance() {
+        return com.google.protobuf.benchmarks.BenchmarkMessage1Proto2.GoogleMessage1
+            .getDefaultInstance();
+      }
+    },
+    GOOGLE_MESSAGE2 {
+      @Override ExtensionRegistry getExtensionRegistry() { return ExtensionRegistry.newInstance(); }
+      @Override
+      Message getDefaultInstance() {
+        return com.google.protobuf.benchmarks.BenchmarkMessage2.GoogleMessage2.getDefaultInstance();
+      }
+    },
+    GOOGLE_MESSAGE3 {
+      @Override
+      ExtensionRegistry getExtensionRegistry() {
+        ExtensionRegistry extensions = ExtensionRegistry.newInstance();
+        benchmarks.google_message3.BenchmarkMessage38.registerAllExtensions(extensions);
+        benchmarks.google_message3.BenchmarkMessage37.registerAllExtensions(extensions);
+        benchmarks.google_message3.BenchmarkMessage36.registerAllExtensions(extensions);
+        benchmarks.google_message3.BenchmarkMessage35.registerAllExtensions(extensions);
+        benchmarks.google_message3.BenchmarkMessage34.registerAllExtensions(extensions);
+        benchmarks.google_message3.BenchmarkMessage33.registerAllExtensions(extensions);
+        benchmarks.google_message3.BenchmarkMessage32.registerAllExtensions(extensions);
+        benchmarks.google_message3.BenchmarkMessage31.registerAllExtensions(extensions);
+        benchmarks.google_message3.BenchmarkMessage3.registerAllExtensions(extensions);
+        return extensions;
+      }
+      @Override
+      Message getDefaultInstance() {
+        return benchmarks.google_message3.BenchmarkMessage3.GoogleMessage3.getDefaultInstance();
+      }
+    },
+    GOOGLE_MESSAGE4 {
+      @Override
+      ExtensionRegistry getExtensionRegistry() {
+        ExtensionRegistry extensions = ExtensionRegistry.newInstance();
+        benchmarks.google_message4.BenchmarkMessage43.registerAllExtensions(extensions);
+        benchmarks.google_message4.BenchmarkMessage42.registerAllExtensions(extensions);
+        benchmarks.google_message4.BenchmarkMessage41.registerAllExtensions(extensions);
+        benchmarks.google_message4.BenchmarkMessage4.registerAllExtensions(extensions);
+        return extensions;
+      }
+      @Override
+      Message getDefaultInstance() {
+        return benchmarks.google_message4.BenchmarkMessage4.GoogleMessage4.getDefaultInstance();
+      }
+    };
+    
+    abstract ExtensionRegistry getExtensionRegistry();
+    abstract Message getDefaultInstance();
+  }
+  
+  @Param 
+  private BenchmarkMessageType benchmarkMessageType;
+  @Param
+  private String dataFile;
+  
+  private byte[] inputData;
+  private BenchmarkDataset benchmarkDataset;
+  private Message defaultMessage;
+  private ExtensionRegistry extensions;
+  private List<byte[]> inputDataList;
+  private List<ByteArrayInputStream> inputStreamList;
+  private List<ByteString> inputStringList;
+  private List<Message> sampleMessageList;
+  private int counter;
+  
+  @BeforeExperiment
+  void setUp() throws IOException {
+    inputData = ProtoBench.readAllBytes(dataFile);
+    benchmarkDataset = BenchmarkDataset.parseFrom(inputData);
+    defaultMessage = benchmarkMessageType.getDefaultInstance();
+    extensions = benchmarkMessageType.getExtensionRegistry();
+    inputDataList = new ArrayList<byte[]>();
+    inputStreamList = new ArrayList<ByteArrayInputStream>();
+    inputStringList = new ArrayList<ByteString>();
+    sampleMessageList = new ArrayList<Message>();
+    
+    for (int i = 0; i < benchmarkDataset.getPayloadCount(); i++) {
+      byte[] singleInputData = benchmarkDataset.getPayload(i).toByteArray();
+      inputDataList.add(benchmarkDataset.getPayload(i).toByteArray());
+      inputStreamList.add(new ByteArrayInputStream(
+          benchmarkDataset.getPayload(i).toByteArray()));
+      inputStringList.add(benchmarkDataset.getPayload(i));
+      sampleMessageList.add(
+          defaultMessage.newBuilderForType().mergeFrom(singleInputData, extensions).build());
+    }
+    
+    counter = 0;
+  }
+  
+  
+  @Benchmark
+  void serializeToByteString(int reps) throws IOException {
+    for (int i = 0; i < reps; i++) {
+      sampleMessageList.get(counter % sampleMessageList.size()).toByteString();
+      counter++;
+    }
+  }
+  
+  @Benchmark
+  void serializeToByteArray(int reps) throws IOException {
+    for (int i = 0; i < reps; i++) {
+      sampleMessageList.get(counter % sampleMessageList.size()).toByteArray();
+      counter++;
+    }
+  }
+  
+  @Benchmark
+  void serializeToMemoryStream(int reps) throws IOException {
+    for (int i = 0; i < reps; i++) {
+      ByteArrayOutputStream output = new ByteArrayOutputStream();
+      sampleMessageList.get(counter % sampleMessageList.size()).writeTo(output);
+      counter++;
+    }
+  }
+  
+  @Benchmark
+  void deserializeFromByteString(int reps) throws IOException {
+    for (int i = 0; i < reps; i++) {
+      defaultMessage
+        .newBuilderForType()
+        .mergeFrom(inputStringList.get(counter % inputStringList.size()), extensions)
+        .build();
+      counter++;
+    }
+  }
+  
+  @Benchmark
+  void deserializeFromByteArray(int reps) throws IOException {
+    for (int i = 0; i < reps; i++) {
+      defaultMessage
+        .newBuilderForType()
+        .mergeFrom(inputDataList.get(counter % inputDataList.size()), extensions)
+        .build();
+      counter++;
+    }
+  }
+  
+  @Benchmark
+  void deserializeFromMemoryStream(int reps) throws IOException {
+    for (int i = 0; i < reps; i++) {
+      defaultMessage
+        .newBuilderForType()
+        .mergeFrom(inputStreamList.get(counter % inputStreamList.size()), extensions)
+        .build();
+      inputStreamList.get(counter % inputStreamList.size()).reset();
+      counter++;
+    }
+  }
+}

+ 0 - 3
tests.sh

@@ -44,9 +44,6 @@ build_cpp() {
   # appears to be missing it: https://github.com/travis-ci/travis-ci/issues/6996
   # appears to be missing it: https://github.com/travis-ci/travis-ci/issues/6996
   if [[ $(type cmake 2>/dev/null) ]]; then
   if [[ $(type cmake 2>/dev/null) ]]; then
     # Verify benchmarking code can build successfully.
     # Verify benchmarking code can build successfully.
-    git submodule init
-    git submodule update
-    cd third_party/benchmark && cmake -DCMAKE_BUILD_TYPE=Release && make && cd ../..
     cd benchmarks && make cpp-benchmark && cd ..
     cd benchmarks && make cpp-benchmark && cd ..
   else
   else
     echo ""
     echo ""