1 #region Copyright notice and license 2 // Protocol Buffers - Google's data interchange format 3 // Copyright 2019 Google Inc. All rights reserved. 4 // https://github.com/protocolbuffers/protobuf 5 // 6 // Redistribution and use in source and binary forms, with or without 7 // modification, are permitted provided that the following conditions are 8 // met: 9 // 10 // * Redistributions of source code must retain the above copyright 11 // notice, this list of conditions and the following disclaimer. 12 // * Redistributions in binary form must reproduce the above 13 // copyright notice, this list of conditions and the following disclaimer 14 // in the documentation and/or other materials provided with the 15 // distribution. 16 // * Neither the name of Google Inc. nor the names of its 17 // contributors may be used to endorse or promote products derived from 18 // this software without specific prior written permission. 19 // 20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 #endregion 32 33 using BenchmarkDotNet.Attributes; 34 using System.Collections.Generic; 35 using System.IO; 36 using System.Linq; 37 38 namespace Google.Protobuf.Benchmarks 39 { 40 /// <summary> 41 /// Benchmark for serializing (to a MemoryStream) and deserializing (from a ByteString). 42 /// Over time we may wish to test the various different approaches to serialization and deserialization separately. 43 /// </summary> 44 [MemoryDiagnoser] 45 public class SerializationBenchmark 46 { 47 /// <summary> 48 /// All the configurations to be tested. Add more datasets to the array as they're available. 49 /// (When C# supports proto2, this will increase significantly.) 50 /// </summary> 51 public static SerializationConfig[] Configurations => new[] 52 { 53 new SerializationConfig("dataset.google_message1_proto3.pb") 54 }; 55 56 [ParamsSource(nameof(Configurations))] 57 public SerializationConfig Configuration { get; set; } 58 59 private MessageParser parser; 60 /// <summary> 61 /// Each data set can contain multiple messages in a single file. 62 /// Each "write" operation should write each message in turn, and each "parse" 63 /// operation should parse each message in turn. 64 /// </summary> 65 private List<SubTest> subTests; 66 67 [GlobalSetup] GlobalSetup()68 public void GlobalSetup() 69 { 70 parser = Configuration.Parser; 71 subTests = Configuration.Payloads.Select(p => new SubTest(p, parser.ParseFrom(p))).ToList(); 72 } 73 74 [Benchmark] WriteToStream()75 public void WriteToStream() => subTests.ForEach(item => item.WriteToStream()); 76 77 [Benchmark] ToByteArray()78 public void ToByteArray() => subTests.ForEach(item => item.ToByteArray()); 79 80 [Benchmark] ParseFromByteString()81 public void ParseFromByteString() => subTests.ForEach(item => item.ParseFromByteString(parser)); 82 83 [Benchmark] ParseFromStream()84 public void ParseFromStream() => subTests.ForEach(item => item.ParseFromStream(parser)); 85 86 private class SubTest 87 { 88 private readonly Stream destinationStream; 89 private readonly Stream sourceStream; 90 private readonly ByteString data; 91 private readonly IMessage message; 92 SubTest(ByteString data, IMessage message)93 public SubTest(ByteString data, IMessage message) 94 { 95 destinationStream = new MemoryStream(data.Length); 96 sourceStream = new MemoryStream(data.ToByteArray()); 97 this.data = data; 98 this.message = message; 99 } 100 Reset()101 public void Reset() => destinationStream.Position = 0; 102 WriteToStream()103 public void WriteToStream() 104 { 105 destinationStream.Position = 0; 106 message.WriteTo(destinationStream); 107 } 108 ToByteArray()109 public void ToByteArray() => message.ToByteArray(); 110 111 public void ParseFromByteString(MessageParser parser) => parser.ParseFrom(data); 112 ParseFromStream(MessageParser parser)113 public void ParseFromStream(MessageParser parser) 114 { 115 sourceStream.Position = 0; 116 parser.ParseFrom(sourceStream); 117 } 118 } 119 } 120 } 121