1 
2 package com.google.protobuf;
3 
4 import com.google.caliper.BeforeExperiment;
5 import com.google.caliper.AfterExperiment;
6 import com.google.caliper.Benchmark;
7 import com.google.caliper.Param;
8 import com.google.caliper.api.VmOptions;
9 import com.google.protobuf.ByteString;
10 import com.google.protobuf.CodedOutputStream;
11 import com.google.protobuf.ExtensionRegistry;
12 import com.google.protobuf.Message;
13 import com.google.protobuf.benchmarks.Benchmarks.BenchmarkDataset;
14 import java.io.ByteArrayInputStream;
15 import java.io.ByteArrayOutputStream;
16 import java.io.BufferedWriter;
17 import java.io.File;
18 import java.io.FileNotFoundException;
19 import java.io.FileOutputStream;
20 import java.io.FileWriter;
21 import java.io.IOException;
22 import java.io.RandomAccessFile;
23 import java.util.ArrayList;
24 import java.util.List;
25 
26 // Caliper set CICompilerCount to 1 for making sure compilation doesn't run in parallel with itself,
27 // This makes TieredCompilation not working. We just disable TieredCompilation by default. In master
28 // branch this has been disabled by default in caliper:
29 // https://github.com/google/caliper/blob/master/caliper-runner/src/main/java/com/google/caliper/runner/target/Jvm.java#L38:14
30 // But this haven't been added into most recent release.
31 @VmOptions("-XX:-TieredCompilation")
32 public class ProtoCaliperBenchmark {
33   public enum BenchmarkMessageType {
34     GOOGLE_MESSAGE1_PROTO3 {
getExtensionRegistry()35       @Override ExtensionRegistry getExtensionRegistry() { return ExtensionRegistry.newInstance(); }
36       @Override
getDefaultInstance()37       Message getDefaultInstance() {
38         return com.google.protobuf.benchmarks.BenchmarkMessage1Proto3.GoogleMessage1
39             .getDefaultInstance();
40       }
41     },
42     GOOGLE_MESSAGE1_PROTO2 {
getExtensionRegistry()43       @Override ExtensionRegistry getExtensionRegistry() { return ExtensionRegistry.newInstance(); }
44       @Override
getDefaultInstance()45       Message getDefaultInstance() {
46         return com.google.protobuf.benchmarks.BenchmarkMessage1Proto2.GoogleMessage1
47             .getDefaultInstance();
48       }
49     },
50     GOOGLE_MESSAGE2 {
getExtensionRegistry()51       @Override ExtensionRegistry getExtensionRegistry() { return ExtensionRegistry.newInstance(); }
52       @Override
getDefaultInstance()53       Message getDefaultInstance() {
54         return com.google.protobuf.benchmarks.BenchmarkMessage2.GoogleMessage2.getDefaultInstance();
55       }
56     },
57     GOOGLE_MESSAGE3 {
58       @Override
getExtensionRegistry()59       ExtensionRegistry getExtensionRegistry() {
60         ExtensionRegistry extensions = ExtensionRegistry.newInstance();
61         com.google.protobuf.benchmarks.BenchmarkMessage38.registerAllExtensions(extensions);
62         com.google.protobuf.benchmarks.BenchmarkMessage37.registerAllExtensions(extensions);
63         com.google.protobuf.benchmarks.BenchmarkMessage36.registerAllExtensions(extensions);
64         com.google.protobuf.benchmarks.BenchmarkMessage35.registerAllExtensions(extensions);
65         com.google.protobuf.benchmarks.BenchmarkMessage34.registerAllExtensions(extensions);
66         com.google.protobuf.benchmarks.BenchmarkMessage33.registerAllExtensions(extensions);
67         com.google.protobuf.benchmarks.BenchmarkMessage32.registerAllExtensions(extensions);
68         com.google.protobuf.benchmarks.BenchmarkMessage31.registerAllExtensions(extensions);
69         com.google.protobuf.benchmarks.BenchmarkMessage3.registerAllExtensions(extensions);
70         return extensions;
71       }
72       @Override
getDefaultInstance()73       Message getDefaultInstance() {
74         return com.google.protobuf.benchmarks.BenchmarkMessage3.GoogleMessage3.getDefaultInstance();
75       }
76     },
77     GOOGLE_MESSAGE4 {
78       @Override
getExtensionRegistry()79       ExtensionRegistry getExtensionRegistry() {
80         ExtensionRegistry extensions = ExtensionRegistry.newInstance();
81         com.google.protobuf.benchmarks.BenchmarkMessage43.registerAllExtensions(extensions);
82         com.google.protobuf.benchmarks.BenchmarkMessage42.registerAllExtensions(extensions);
83         com.google.protobuf.benchmarks.BenchmarkMessage41.registerAllExtensions(extensions);
84         com.google.protobuf.benchmarks.BenchmarkMessage4.registerAllExtensions(extensions);
85         return extensions;
86       }
87       @Override
getDefaultInstance()88       Message getDefaultInstance() {
89         return com.google.protobuf.benchmarks.BenchmarkMessage4.GoogleMessage4.getDefaultInstance();
90       }
91     };
92 
getExtensionRegistry()93     abstract ExtensionRegistry getExtensionRegistry();
getDefaultInstance()94     abstract Message getDefaultInstance();
95   }
96 
97   private BenchmarkMessageType benchmarkMessageType;
98   @Param("")
99   private String dataFile;
100 
101   private byte[] inputData;
102   private BenchmarkDataset benchmarkDataset;
103   private Message defaultMessage;
104   private ExtensionRegistry extensions;
105   private List<byte[]> inputDataList;
106   private List<ByteArrayInputStream> inputStreamList;
107   private List<ByteString> inputStringList;
108   private List<Message> sampleMessageList;
109 
getMessageType()110   private BenchmarkMessageType getMessageType() throws IOException {
111     if (benchmarkDataset.getMessageName().equals("benchmarks.proto3.GoogleMessage1")) {
112       return BenchmarkMessageType.GOOGLE_MESSAGE1_PROTO3;
113     } else if (benchmarkDataset.getMessageName().equals("benchmarks.proto2.GoogleMessage1")) {
114       return BenchmarkMessageType.GOOGLE_MESSAGE1_PROTO2;
115     } else if (benchmarkDataset.getMessageName().equals("benchmarks.proto2.GoogleMessage2")) {
116       return BenchmarkMessageType.GOOGLE_MESSAGE2;
117     } else if (benchmarkDataset.getMessageName().
118         equals("benchmarks.google_message3.GoogleMessage3")) {
119       return BenchmarkMessageType.GOOGLE_MESSAGE3;
120     } else if (benchmarkDataset.getMessageName().
121         equals("benchmarks.google_message4.GoogleMessage4")) {
122       return BenchmarkMessageType.GOOGLE_MESSAGE4;
123     } else {
124       throw new IllegalStateException("Invalid DataFile! There's no testing message named "
125           + benchmarkDataset.getMessageName());
126     }
127   }
128 
129   @BeforeExperiment
setUp()130   void setUp() throws IOException {
131     if (!dataFile.equals("")) {
132       RandomAccessFile file = new RandomAccessFile(new File(dataFile), "r");
133       inputData = new byte[(int) file.length()];
134       file.readFully(inputData);
135       benchmarkDataset = BenchmarkDataset.parseFrom(inputData);
136       benchmarkMessageType = getMessageType();
137     } else {
138       inputData = new byte[0];
139       benchmarkDataset = BenchmarkDataset.parseFrom(inputData);
140       benchmarkMessageType = BenchmarkMessageType.GOOGLE_MESSAGE2;
141     }
142     defaultMessage = benchmarkMessageType.getDefaultInstance();
143     extensions = benchmarkMessageType.getExtensionRegistry();
144     inputDataList = new ArrayList<byte[]>();
145     inputStreamList = new ArrayList<ByteArrayInputStream>();
146     inputStringList = new ArrayList<ByteString>();
147     sampleMessageList = new ArrayList<Message>();
148 
149     for (int i = 0; i < benchmarkDataset.getPayloadCount(); i++) {
150       byte[] singleInputData = benchmarkDataset.getPayload(i).toByteArray();
151       inputDataList.add(benchmarkDataset.getPayload(i).toByteArray());
152       inputStreamList.add(new ByteArrayInputStream(
153           benchmarkDataset.getPayload(i).toByteArray()));
154       inputStringList.add(benchmarkDataset.getPayload(i));
155       sampleMessageList.add(
156           defaultMessage.newBuilderForType().mergeFrom(singleInputData, extensions).build());
157     }
158   }
159 
160 
161   @Benchmark
serializeToByteArray(int reps)162   void serializeToByteArray(int reps) throws IOException {
163     if (sampleMessageList.size() == 0) {
164       return;
165     }
166     for (int i = 0; i < reps; i++) {
167       for (int j = 0; j < sampleMessageList.size(); j++) {
168         sampleMessageList.get(j).toByteArray();
169       }
170     }
171   }
172 
173   @Benchmark
serializeToMemoryStream(int reps)174   void serializeToMemoryStream(int reps) throws IOException {
175     if (sampleMessageList.size() == 0) {
176       return;
177     }
178     for (int i = 0; i < reps; i++) {
179       for (int j = 0; j < sampleMessageList.size(); j++) {
180         ByteArrayOutputStream output = new ByteArrayOutputStream();
181         sampleMessageList.get(j).writeTo(output);
182       }
183     }
184   }
185 
186   @Benchmark
deserializeFromByteArray(int reps)187   void deserializeFromByteArray(int reps) throws IOException {
188     if (inputDataList.size() == 0) {
189       return;
190     }
191     for (int i = 0; i < reps; i++) {
192       for (int j = 0; j < inputDataList.size(); j++) {
193         benchmarkMessageType.getDefaultInstance().getParserForType().parseFrom(
194           inputDataList.get(j), extensions);
195       }
196     }
197   }
198 
199   @Benchmark
deserializeFromMemoryStream(int reps)200   void deserializeFromMemoryStream(int reps) throws IOException {
201     if (inputStreamList.size() == 0) {
202       return;
203     }
204     for (int i = 0; i < reps; i++) {
205       for (int j = 0; j < inputStreamList.size(); j++) {
206         benchmarkMessageType.getDefaultInstance().getParserForType().parseFrom(
207             inputStreamList.get(j), extensions);
208         inputStreamList.get(j).reset();
209       }
210     }
211   }
212 }
213 
214 
215