/thirdparty/breakpad/third_party/protobuf/protobuf/benchmarks/ProtoBench.java

http://github.com/tomahawk-player/tomahawk · Java · 203 lines · 144 code · 15 blank · 44 comment · 9 complexity · de22de601c268aaee37c844d5aee612c MD5 · raw file

  1. // Protocol Buffers - Google's data interchange format
  2. // Copyright 2009 Google Inc. All rights reserved.
  3. // http://code.google.com/p/protobuf/
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are
  7. // met:
  8. //
  9. // * Redistributions of source code must retain the above copyright
  10. // notice, this list of conditions and the following disclaimer.
  11. // * Redistributions in binary form must reproduce the above
  12. // copyright notice, this list of conditions and the following disclaimer
  13. // in the documentation and/or other materials provided with the
  14. // distribution.
  15. // * Neither the name of Google Inc. nor the names of its
  16. // contributors may be used to endorse or promote products derived from
  17. // this software without specific prior written permission.
  18. //
  19. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. package com.google.protocolbuffers;
  31. import java.io.ByteArrayInputStream;
  32. import java.io.ByteArrayOutputStream;
  33. import java.io.File;
  34. import java.io.FileOutputStream;
  35. import java.io.FileNotFoundException;
  36. import java.io.IOException;
  37. import java.io.RandomAccessFile;
  38. import java.lang.reflect.Method;
  39. import com.google.protobuf.ByteString;
  40. import com.google.protobuf.CodedInputStream;
  41. import com.google.protobuf.CodedOutputStream;
  42. import com.google.protobuf.Message;
  43. public class ProtoBench {
  44. private static final long MIN_SAMPLE_TIME_MS = 2 * 1000;
  45. private static final long TARGET_TIME_MS = 30 * 1000;
  46. private ProtoBench() {
  47. // Prevent instantiation
  48. }
  49. public static void main(String[] args) {
  50. if (args.length < 2 || (args.length % 2) != 0) {
  51. System.err.println("Usage: ProtoBench <descriptor type name> <input data>");
  52. System.err.println("The descriptor type name is the fully-qualified message name,");
  53. System.err.println("e.g. com.google.protocolbuffers.benchmark.Message1");
  54. System.err.println("(You can specify multiple pairs of descriptor type name and input data.)");
  55. System.exit(1);
  56. }
  57. boolean success = true;
  58. for (int i = 0; i < args.length; i += 2) {
  59. success &= runTest(args[i], args[i + 1]);
  60. }
  61. System.exit(success ? 0 : 1);
  62. }
  63. /**
  64. * Runs a single test. Error messages are displayed to stderr, and the return value
  65. * indicates general success/failure.
  66. */
  67. public static boolean runTest(String type, String file) {
  68. System.out.println("Benchmarking " + type + " with file " + file);
  69. final Message defaultMessage;
  70. try {
  71. Class<?> clazz = Class.forName(type);
  72. Method method = clazz.getDeclaredMethod("getDefaultInstance");
  73. defaultMessage = (Message) method.invoke(null);
  74. } catch (Exception e) {
  75. // We want to do the same thing with all exceptions. Not generally nice,
  76. // but this is slightly different.
  77. System.err.println("Unable to get default message for " + type);
  78. return false;
  79. }
  80. try {
  81. final byte[] inputData = readAllBytes(file);
  82. final ByteArrayInputStream inputStream = new ByteArrayInputStream(inputData);
  83. final ByteString inputString = ByteString.copyFrom(inputData);
  84. final Message sampleMessage = defaultMessage.newBuilderForType().mergeFrom(inputString).build();
  85. FileOutputStream devNullTemp = null;
  86. CodedOutputStream reuseDevNullTemp = null;
  87. try {
  88. devNullTemp = new FileOutputStream("/dev/null");
  89. reuseDevNullTemp = CodedOutputStream.newInstance(devNullTemp);
  90. } catch (FileNotFoundException e) {
  91. // ignore: this is probably Windows, where /dev/null does not exist
  92. }
  93. final FileOutputStream devNull = devNullTemp;
  94. final CodedOutputStream reuseDevNull = reuseDevNullTemp;
  95. benchmark("Serialize to byte string", inputData.length, new Action() {
  96. public void execute() { sampleMessage.toByteString(); }
  97. });
  98. benchmark("Serialize to byte array", inputData.length, new Action() {
  99. public void execute() { sampleMessage.toByteArray(); }
  100. });
  101. benchmark("Serialize to memory stream", inputData.length, new Action() {
  102. public void execute() throws IOException {
  103. sampleMessage.writeTo(new ByteArrayOutputStream());
  104. }
  105. });
  106. if (devNull != null) {
  107. benchmark("Serialize to /dev/null with FileOutputStream", inputData.length, new Action() {
  108. public void execute() throws IOException {
  109. sampleMessage.writeTo(devNull);
  110. }
  111. });
  112. benchmark("Serialize to /dev/null reusing FileOutputStream", inputData.length, new Action() {
  113. public void execute() throws IOException {
  114. sampleMessage.writeTo(reuseDevNull);
  115. reuseDevNull.flush(); // force the write to the OutputStream
  116. }
  117. });
  118. }
  119. benchmark("Deserialize from byte string", inputData.length, new Action() {
  120. public void execute() throws IOException {
  121. defaultMessage.newBuilderForType().mergeFrom(inputString).build();
  122. }
  123. });
  124. benchmark("Deserialize from byte array", inputData.length, new Action() {
  125. public void execute() throws IOException {
  126. defaultMessage.newBuilderForType()
  127. .mergeFrom(CodedInputStream.newInstance(inputData)).build();
  128. }
  129. });
  130. benchmark("Deserialize from memory stream", inputData.length, new Action() {
  131. public void execute() throws IOException {
  132. defaultMessage.newBuilderForType()
  133. .mergeFrom(CodedInputStream.newInstance(inputStream)).build();
  134. inputStream.reset();
  135. }
  136. });
  137. System.out.println();
  138. return true;
  139. } catch (Exception e) {
  140. System.err.println("Error: " + e.getMessage());
  141. System.err.println("Detailed exception information:");
  142. e.printStackTrace(System.err);
  143. return false;
  144. }
  145. }
  146. private static void benchmark(String name, long dataSize, Action action) throws IOException {
  147. // Make sure it's JITted "reasonably" hard before running the first progress test
  148. for (int i=0; i < 100; i++) {
  149. action.execute();
  150. }
  151. // Run it progressively more times until we've got a reasonable sample
  152. int iterations = 1;
  153. long elapsed = timeAction(action, iterations);
  154. while (elapsed < MIN_SAMPLE_TIME_MS) {
  155. iterations *= 2;
  156. elapsed = timeAction(action, iterations);
  157. }
  158. // Upscale the sample to the target time. Do this in floating point arithmetic
  159. // to avoid overflow issues.
  160. iterations = (int) ((TARGET_TIME_MS / (double) elapsed) * iterations);
  161. elapsed = timeAction(action, iterations);
  162. System.out.println(name + ": " + iterations + " iterations in "
  163. + (elapsed/1000f) + "s; "
  164. + (iterations * dataSize) / (elapsed * 1024 * 1024 / 1000f)
  165. + "MB/s");
  166. }
  167. private static long timeAction(Action action, int iterations) throws IOException {
  168. System.gc();
  169. long start = System.currentTimeMillis();
  170. for (int i = 0; i < iterations; i++) {
  171. action.execute();
  172. }
  173. long end = System.currentTimeMillis();
  174. return end - start;
  175. }
  176. private static byte[] readAllBytes(String filename) throws IOException {
  177. RandomAccessFile file = new RandomAccessFile(new File(filename), "r");
  178. byte[] content = new byte[(int) file.length()];
  179. file.readFully(content);
  180. return content;
  181. }
  182. /**
  183. * Interface used to capture a single action to benchmark.
  184. */
  185. interface Action {
  186. void execute() throws IOException;
  187. }
  188. }