1*1b3f573fSAndroid Build Coastguard Worker #region Copyright notice and license 2*1b3f573fSAndroid Build Coastguard Worker // Protocol Buffers - Google's data interchange format 3*1b3f573fSAndroid Build Coastguard Worker // Copyright 2019 Google Inc. All rights reserved. 4*1b3f573fSAndroid Build Coastguard Worker // https://github.com/protocolbuffers/protobuf 5*1b3f573fSAndroid Build Coastguard Worker // 6*1b3f573fSAndroid Build Coastguard Worker // Redistribution and use in source and binary forms, with or without 7*1b3f573fSAndroid Build Coastguard Worker // modification, are permitted provided that the following conditions are 8*1b3f573fSAndroid Build Coastguard Worker // met: 9*1b3f573fSAndroid Build Coastguard Worker // 10*1b3f573fSAndroid Build Coastguard Worker // * Redistributions of source code must retain the above copyright 11*1b3f573fSAndroid Build Coastguard Worker // notice, this list of conditions and the following disclaimer. 12*1b3f573fSAndroid Build Coastguard Worker // * Redistributions in binary form must reproduce the above 13*1b3f573fSAndroid Build Coastguard Worker // copyright notice, this list of conditions and the following disclaimer 14*1b3f573fSAndroid Build Coastguard Worker // in the documentation and/or other materials provided with the 15*1b3f573fSAndroid Build Coastguard Worker // distribution. 16*1b3f573fSAndroid Build Coastguard Worker // * Neither the name of Google Inc. nor the names of its 17*1b3f573fSAndroid Build Coastguard Worker // contributors may be used to endorse or promote products derived from 18*1b3f573fSAndroid Build Coastguard Worker // this software without specific prior written permission. 19*1b3f573fSAndroid Build Coastguard Worker // 20*1b3f573fSAndroid Build Coastguard Worker // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21*1b3f573fSAndroid Build Coastguard Worker // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22*1b3f573fSAndroid Build Coastguard Worker // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23*1b3f573fSAndroid Build Coastguard Worker // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24*1b3f573fSAndroid Build Coastguard Worker // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25*1b3f573fSAndroid Build Coastguard Worker // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26*1b3f573fSAndroid Build Coastguard Worker // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27*1b3f573fSAndroid Build Coastguard Worker // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28*1b3f573fSAndroid Build Coastguard Worker // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29*1b3f573fSAndroid Build Coastguard Worker // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30*1b3f573fSAndroid Build Coastguard Worker // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31*1b3f573fSAndroid Build Coastguard Worker #endregion 32*1b3f573fSAndroid Build Coastguard Worker 33*1b3f573fSAndroid Build Coastguard Worker using BenchmarkDotNet.Attributes; 34*1b3f573fSAndroid Build Coastguard Worker using System; 35*1b3f573fSAndroid Build Coastguard Worker using System.Buffers.Binary; 36*1b3f573fSAndroid Build Coastguard Worker using System.Collections.Generic; 37*1b3f573fSAndroid Build Coastguard Worker using System.IO; 38*1b3f573fSAndroid Build Coastguard Worker using System.Buffers; 39*1b3f573fSAndroid Build Coastguard Worker using System.Text; 40*1b3f573fSAndroid Build Coastguard Worker 41*1b3f573fSAndroid Build Coastguard Worker namespace Google.Protobuf.Benchmarks 42*1b3f573fSAndroid Build Coastguard Worker { 43*1b3f573fSAndroid Build Coastguard Worker /// <summary> 44*1b3f573fSAndroid Build Coastguard Worker /// Benchmarks throughput when writing raw primitives. 45*1b3f573fSAndroid Build Coastguard Worker /// </summary> 46*1b3f573fSAndroid Build Coastguard Worker [MemoryDiagnoser] 47*1b3f573fSAndroid Build Coastguard Worker public class WriteRawPrimitivesBenchmark 48*1b3f573fSAndroid Build Coastguard Worker { 49*1b3f573fSAndroid Build Coastguard Worker // key is the encodedSize of varint values 50*1b3f573fSAndroid Build Coastguard Worker Dictionary<int, uint[]> varint32Values; 51*1b3f573fSAndroid Build Coastguard Worker Dictionary<int, ulong[]> varint64Values; 52*1b3f573fSAndroid Build Coastguard Worker 53*1b3f573fSAndroid Build Coastguard Worker double[] doubleValues; 54*1b3f573fSAndroid Build Coastguard Worker float[] floatValues; 55*1b3f573fSAndroid Build Coastguard Worker 56*1b3f573fSAndroid Build Coastguard Worker // key is the encodedSize of string values 57*1b3f573fSAndroid Build Coastguard Worker Dictionary<int, string[]> stringValues; 58*1b3f573fSAndroid Build Coastguard Worker 59*1b3f573fSAndroid Build Coastguard Worker // key is the encodedSize of string values 60*1b3f573fSAndroid Build Coastguard Worker Dictionary<int, string[]> nonAsciiStringValues; 61*1b3f573fSAndroid Build Coastguard Worker 62*1b3f573fSAndroid Build Coastguard Worker // key is the encodedSize of string values 63*1b3f573fSAndroid Build Coastguard Worker Dictionary<int, ByteString[]> byteStringValues; 64*1b3f573fSAndroid Build Coastguard Worker 65*1b3f573fSAndroid Build Coastguard Worker // the buffer to which all the data will be written 66*1b3f573fSAndroid Build Coastguard Worker byte[] outputBuffer; 67*1b3f573fSAndroid Build Coastguard Worker 68*1b3f573fSAndroid Build Coastguard Worker Random random = new Random(417384220); // random but deterministic seed 69*1b3f573fSAndroid Build Coastguard Worker 70*1b3f573fSAndroid Build Coastguard Worker public IEnumerable<int> StringEncodedSizes => new[] { 1, 4, 10, 105, 10080 }; 71*1b3f573fSAndroid Build Coastguard Worker 72*1b3f573fSAndroid Build Coastguard Worker public IEnumerable<int> NonAsciiStringEncodedSizes => new[] { 4, 10, 105, 10080 }; 73*1b3f573fSAndroid Build Coastguard Worker 74*1b3f573fSAndroid Build Coastguard Worker [GlobalSetup] GlobalSetup()75*1b3f573fSAndroid Build Coastguard Worker public void GlobalSetup() 76*1b3f573fSAndroid Build Coastguard Worker { 77*1b3f573fSAndroid Build Coastguard Worker outputBuffer = new byte[BytesToWrite]; 78*1b3f573fSAndroid Build Coastguard Worker 79*1b3f573fSAndroid Build Coastguard Worker varint32Values = new Dictionary<int, uint[]>(); 80*1b3f573fSAndroid Build Coastguard Worker varint64Values = new Dictionary<int, ulong[]>(); 81*1b3f573fSAndroid Build Coastguard Worker for (int encodedSize = 1; encodedSize <= 10; encodedSize++) 82*1b3f573fSAndroid Build Coastguard Worker { 83*1b3f573fSAndroid Build Coastguard Worker if (encodedSize <= 5) 84*1b3f573fSAndroid Build Coastguard Worker { 85*1b3f573fSAndroid Build Coastguard Worker varint32Values.Add(encodedSize, CreateRandomVarints32(random, BytesToWrite / encodedSize, encodedSize)); 86*1b3f573fSAndroid Build Coastguard Worker } 87*1b3f573fSAndroid Build Coastguard Worker varint64Values.Add(encodedSize, CreateRandomVarints64(random, BytesToWrite / encodedSize, encodedSize)); 88*1b3f573fSAndroid Build Coastguard Worker } 89*1b3f573fSAndroid Build Coastguard Worker 90*1b3f573fSAndroid Build Coastguard Worker doubleValues = CreateRandomDoubles(random, BytesToWrite / sizeof(double)); 91*1b3f573fSAndroid Build Coastguard Worker floatValues = CreateRandomFloats(random, BytesToWrite / sizeof(float)); 92*1b3f573fSAndroid Build Coastguard Worker 93*1b3f573fSAndroid Build Coastguard Worker stringValues = new Dictionary<int, string[]>(); 94*1b3f573fSAndroid Build Coastguard Worker 95*1b3f573fSAndroid Build Coastguard Worker byteStringValues = new Dictionary<int, ByteString[]>(); 96*1b3f573fSAndroid Build Coastguard Worker foreach(var encodedSize in StringEncodedSizes) 97*1b3f573fSAndroid Build Coastguard Worker { 98*1b3f573fSAndroid Build Coastguard Worker stringValues.Add(encodedSize, CreateStrings(BytesToWrite / encodedSize, encodedSize)); 99*1b3f573fSAndroid Build Coastguard Worker byteStringValues.Add(encodedSize, CreateByteStrings(BytesToWrite / encodedSize, encodedSize)); 100*1b3f573fSAndroid Build Coastguard Worker } 101*1b3f573fSAndroid Build Coastguard Worker 102*1b3f573fSAndroid Build Coastguard Worker nonAsciiStringValues = new Dictionary<int, string[]>(); 103*1b3f573fSAndroid Build Coastguard Worker foreach(var encodedSize in NonAsciiStringEncodedSizes) 104*1b3f573fSAndroid Build Coastguard Worker { 105*1b3f573fSAndroid Build Coastguard Worker nonAsciiStringValues.Add(encodedSize, CreateNonAsciiStrings(BytesToWrite / encodedSize, encodedSize)); 106*1b3f573fSAndroid Build Coastguard Worker } 107*1b3f573fSAndroid Build Coastguard Worker } 108*1b3f573fSAndroid Build Coastguard Worker 109*1b3f573fSAndroid Build Coastguard Worker // Total number of bytes that each benchmark will write. 110*1b3f573fSAndroid Build Coastguard Worker // Measuring the time taken to write buffer of given size makes it easier to compare parsing speed for different 111*1b3f573fSAndroid Build Coastguard Worker // types and makes it easy to calculate the througput (in MB/s) 112*1b3f573fSAndroid Build Coastguard Worker // 10800 bytes is chosen because it is divisible by all possible encoded sizes for all primitive types {1..10} 113*1b3f573fSAndroid Build Coastguard Worker [Params(10080)] 114*1b3f573fSAndroid Build Coastguard Worker public int BytesToWrite { get; set; } 115*1b3f573fSAndroid Build Coastguard Worker 116*1b3f573fSAndroid Build Coastguard Worker [Benchmark] 117*1b3f573fSAndroid Build Coastguard Worker [Arguments(1)] 118*1b3f573fSAndroid Build Coastguard Worker [Arguments(2)] 119*1b3f573fSAndroid Build Coastguard Worker [Arguments(3)] 120*1b3f573fSAndroid Build Coastguard Worker [Arguments(4)] 121*1b3f573fSAndroid Build Coastguard Worker [Arguments(5)] WriteRawVarint32_CodedOutputStream(int encodedSize)122*1b3f573fSAndroid Build Coastguard Worker public void WriteRawVarint32_CodedOutputStream(int encodedSize) 123*1b3f573fSAndroid Build Coastguard Worker { 124*1b3f573fSAndroid Build Coastguard Worker var values = varint32Values[encodedSize]; 125*1b3f573fSAndroid Build Coastguard Worker var cos = new CodedOutputStream(outputBuffer); 126*1b3f573fSAndroid Build Coastguard Worker for (int i = 0; i < values.Length; i++) 127*1b3f573fSAndroid Build Coastguard Worker { 128*1b3f573fSAndroid Build Coastguard Worker cos.WriteRawVarint32(values[i]); 129*1b3f573fSAndroid Build Coastguard Worker } 130*1b3f573fSAndroid Build Coastguard Worker cos.Flush(); 131*1b3f573fSAndroid Build Coastguard Worker cos.CheckNoSpaceLeft(); 132*1b3f573fSAndroid Build Coastguard Worker } 133*1b3f573fSAndroid Build Coastguard Worker 134*1b3f573fSAndroid Build Coastguard Worker [Benchmark] 135*1b3f573fSAndroid Build Coastguard Worker [Arguments(1)] 136*1b3f573fSAndroid Build Coastguard Worker [Arguments(2)] 137*1b3f573fSAndroid Build Coastguard Worker [Arguments(3)] 138*1b3f573fSAndroid Build Coastguard Worker [Arguments(4)] 139*1b3f573fSAndroid Build Coastguard Worker [Arguments(5)] WriteRawVarint32_WriteContext(int encodedSize)140*1b3f573fSAndroid Build Coastguard Worker public void WriteRawVarint32_WriteContext(int encodedSize) 141*1b3f573fSAndroid Build Coastguard Worker { 142*1b3f573fSAndroid Build Coastguard Worker var values = varint32Values[encodedSize]; 143*1b3f573fSAndroid Build Coastguard Worker var span = new Span<byte>(outputBuffer); 144*1b3f573fSAndroid Build Coastguard Worker WriteContext.Initialize(ref span, out WriteContext ctx); 145*1b3f573fSAndroid Build Coastguard Worker for (int i = 0; i < values.Length; i++) 146*1b3f573fSAndroid Build Coastguard Worker { 147*1b3f573fSAndroid Build Coastguard Worker ctx.WriteUInt32(values[i]); 148*1b3f573fSAndroid Build Coastguard Worker } 149*1b3f573fSAndroid Build Coastguard Worker ctx.Flush(); 150*1b3f573fSAndroid Build Coastguard Worker ctx.CheckNoSpaceLeft(); 151*1b3f573fSAndroid Build Coastguard Worker } 152*1b3f573fSAndroid Build Coastguard Worker 153*1b3f573fSAndroid Build Coastguard Worker [Benchmark] 154*1b3f573fSAndroid Build Coastguard Worker [Arguments(1)] 155*1b3f573fSAndroid Build Coastguard Worker [Arguments(2)] 156*1b3f573fSAndroid Build Coastguard Worker [Arguments(3)] 157*1b3f573fSAndroid Build Coastguard Worker [Arguments(4)] 158*1b3f573fSAndroid Build Coastguard Worker [Arguments(5)] 159*1b3f573fSAndroid Build Coastguard Worker [Arguments(6)] 160*1b3f573fSAndroid Build Coastguard Worker [Arguments(7)] 161*1b3f573fSAndroid Build Coastguard Worker [Arguments(8)] 162*1b3f573fSAndroid Build Coastguard Worker [Arguments(9)] 163*1b3f573fSAndroid Build Coastguard Worker [Arguments(10)] WriteRawVarint64_CodedOutputStream(int encodedSize)164*1b3f573fSAndroid Build Coastguard Worker public void WriteRawVarint64_CodedOutputStream(int encodedSize) 165*1b3f573fSAndroid Build Coastguard Worker { 166*1b3f573fSAndroid Build Coastguard Worker var values = varint64Values[encodedSize]; 167*1b3f573fSAndroid Build Coastguard Worker var cos = new CodedOutputStream(outputBuffer); 168*1b3f573fSAndroid Build Coastguard Worker for (int i = 0; i < values.Length; i++) 169*1b3f573fSAndroid Build Coastguard Worker { 170*1b3f573fSAndroid Build Coastguard Worker cos.WriteRawVarint64(values[i]); 171*1b3f573fSAndroid Build Coastguard Worker } 172*1b3f573fSAndroid Build Coastguard Worker cos.Flush(); 173*1b3f573fSAndroid Build Coastguard Worker cos.CheckNoSpaceLeft(); 174*1b3f573fSAndroid Build Coastguard Worker } 175*1b3f573fSAndroid Build Coastguard Worker 176*1b3f573fSAndroid Build Coastguard Worker [Benchmark] 177*1b3f573fSAndroid Build Coastguard Worker [Arguments(1)] 178*1b3f573fSAndroid Build Coastguard Worker [Arguments(2)] 179*1b3f573fSAndroid Build Coastguard Worker [Arguments(3)] 180*1b3f573fSAndroid Build Coastguard Worker [Arguments(4)] 181*1b3f573fSAndroid Build Coastguard Worker [Arguments(5)] 182*1b3f573fSAndroid Build Coastguard Worker [Arguments(6)] 183*1b3f573fSAndroid Build Coastguard Worker [Arguments(7)] 184*1b3f573fSAndroid Build Coastguard Worker [Arguments(8)] 185*1b3f573fSAndroid Build Coastguard Worker [Arguments(9)] 186*1b3f573fSAndroid Build Coastguard Worker [Arguments(10)] WriteRawVarint64_WriteContext(int encodedSize)187*1b3f573fSAndroid Build Coastguard Worker public void WriteRawVarint64_WriteContext(int encodedSize) 188*1b3f573fSAndroid Build Coastguard Worker { 189*1b3f573fSAndroid Build Coastguard Worker var values = varint64Values[encodedSize]; 190*1b3f573fSAndroid Build Coastguard Worker var span = new Span<byte>(outputBuffer); 191*1b3f573fSAndroid Build Coastguard Worker WriteContext.Initialize(ref span, out WriteContext ctx); 192*1b3f573fSAndroid Build Coastguard Worker for (int i = 0; i < values.Length; i++) 193*1b3f573fSAndroid Build Coastguard Worker { 194*1b3f573fSAndroid Build Coastguard Worker ctx.WriteUInt64(values[i]); 195*1b3f573fSAndroid Build Coastguard Worker } 196*1b3f573fSAndroid Build Coastguard Worker ctx.Flush(); 197*1b3f573fSAndroid Build Coastguard Worker ctx.CheckNoSpaceLeft(); 198*1b3f573fSAndroid Build Coastguard Worker } 199*1b3f573fSAndroid Build Coastguard Worker 200*1b3f573fSAndroid Build Coastguard Worker [Benchmark] WriteFixed32_CodedOutputStream()201*1b3f573fSAndroid Build Coastguard Worker public void WriteFixed32_CodedOutputStream() 202*1b3f573fSAndroid Build Coastguard Worker { 203*1b3f573fSAndroid Build Coastguard Worker const int encodedSize = sizeof(uint); 204*1b3f573fSAndroid Build Coastguard Worker var cos = new CodedOutputStream(outputBuffer); 205*1b3f573fSAndroid Build Coastguard Worker for (int i = 0; i < BytesToWrite / encodedSize; i++) 206*1b3f573fSAndroid Build Coastguard Worker { 207*1b3f573fSAndroid Build Coastguard Worker cos.WriteFixed32(12345); 208*1b3f573fSAndroid Build Coastguard Worker } 209*1b3f573fSAndroid Build Coastguard Worker cos.Flush(); 210*1b3f573fSAndroid Build Coastguard Worker cos.CheckNoSpaceLeft(); 211*1b3f573fSAndroid Build Coastguard Worker } 212*1b3f573fSAndroid Build Coastguard Worker 213*1b3f573fSAndroid Build Coastguard Worker [Benchmark] WriteFixed32_WriteContext()214*1b3f573fSAndroid Build Coastguard Worker public void WriteFixed32_WriteContext() 215*1b3f573fSAndroid Build Coastguard Worker { 216*1b3f573fSAndroid Build Coastguard Worker const int encodedSize = sizeof(uint); 217*1b3f573fSAndroid Build Coastguard Worker var span = new Span<byte>(outputBuffer); 218*1b3f573fSAndroid Build Coastguard Worker WriteContext.Initialize(ref span, out WriteContext ctx); 219*1b3f573fSAndroid Build Coastguard Worker for (uint i = 0; i < BytesToWrite / encodedSize; i++) 220*1b3f573fSAndroid Build Coastguard Worker { 221*1b3f573fSAndroid Build Coastguard Worker ctx.WriteFixed32(12345); 222*1b3f573fSAndroid Build Coastguard Worker } 223*1b3f573fSAndroid Build Coastguard Worker ctx.Flush(); 224*1b3f573fSAndroid Build Coastguard Worker ctx.CheckNoSpaceLeft(); 225*1b3f573fSAndroid Build Coastguard Worker } 226*1b3f573fSAndroid Build Coastguard Worker 227*1b3f573fSAndroid Build Coastguard Worker [Benchmark] WriteFixed64_CodedOutputStream()228*1b3f573fSAndroid Build Coastguard Worker public void WriteFixed64_CodedOutputStream() 229*1b3f573fSAndroid Build Coastguard Worker { 230*1b3f573fSAndroid Build Coastguard Worker const int encodedSize = sizeof(ulong); 231*1b3f573fSAndroid Build Coastguard Worker var cos = new CodedOutputStream(outputBuffer); 232*1b3f573fSAndroid Build Coastguard Worker for(int i = 0; i < BytesToWrite / encodedSize; i++) 233*1b3f573fSAndroid Build Coastguard Worker { 234*1b3f573fSAndroid Build Coastguard Worker cos.WriteFixed64(123456789); 235*1b3f573fSAndroid Build Coastguard Worker } 236*1b3f573fSAndroid Build Coastguard Worker cos.Flush(); 237*1b3f573fSAndroid Build Coastguard Worker cos.CheckNoSpaceLeft(); 238*1b3f573fSAndroid Build Coastguard Worker } 239*1b3f573fSAndroid Build Coastguard Worker 240*1b3f573fSAndroid Build Coastguard Worker [Benchmark] WriteFixed64_WriteContext()241*1b3f573fSAndroid Build Coastguard Worker public void WriteFixed64_WriteContext() 242*1b3f573fSAndroid Build Coastguard Worker { 243*1b3f573fSAndroid Build Coastguard Worker const int encodedSize = sizeof(ulong); 244*1b3f573fSAndroid Build Coastguard Worker var span = new Span<byte>(outputBuffer); 245*1b3f573fSAndroid Build Coastguard Worker WriteContext.Initialize(ref span, out WriteContext ctx); 246*1b3f573fSAndroid Build Coastguard Worker for (uint i = 0; i < BytesToWrite / encodedSize; i++) 247*1b3f573fSAndroid Build Coastguard Worker { 248*1b3f573fSAndroid Build Coastguard Worker ctx.WriteFixed64(123456789); 249*1b3f573fSAndroid Build Coastguard Worker } 250*1b3f573fSAndroid Build Coastguard Worker ctx.Flush(); 251*1b3f573fSAndroid Build Coastguard Worker ctx.CheckNoSpaceLeft(); 252*1b3f573fSAndroid Build Coastguard Worker } 253*1b3f573fSAndroid Build Coastguard Worker 254*1b3f573fSAndroid Build Coastguard Worker [Benchmark] WriteRawTag_OneByte_WriteContext()255*1b3f573fSAndroid Build Coastguard Worker public void WriteRawTag_OneByte_WriteContext() 256*1b3f573fSAndroid Build Coastguard Worker { 257*1b3f573fSAndroid Build Coastguard Worker const int encodedSize = 1; 258*1b3f573fSAndroid Build Coastguard Worker var span = new Span<byte>(outputBuffer); 259*1b3f573fSAndroid Build Coastguard Worker WriteContext.Initialize(ref span, out WriteContext ctx); 260*1b3f573fSAndroid Build Coastguard Worker for (uint i = 0; i < BytesToWrite / encodedSize; i++) 261*1b3f573fSAndroid Build Coastguard Worker { 262*1b3f573fSAndroid Build Coastguard Worker ctx.WriteRawTag(16); 263*1b3f573fSAndroid Build Coastguard Worker } 264*1b3f573fSAndroid Build Coastguard Worker ctx.Flush(); 265*1b3f573fSAndroid Build Coastguard Worker ctx.CheckNoSpaceLeft(); 266*1b3f573fSAndroid Build Coastguard Worker } 267*1b3f573fSAndroid Build Coastguard Worker 268*1b3f573fSAndroid Build Coastguard Worker [Benchmark] WriteRawTag_TwoBytes_WriteContext()269*1b3f573fSAndroid Build Coastguard Worker public void WriteRawTag_TwoBytes_WriteContext() 270*1b3f573fSAndroid Build Coastguard Worker { 271*1b3f573fSAndroid Build Coastguard Worker const int encodedSize = 2; 272*1b3f573fSAndroid Build Coastguard Worker var span = new Span<byte>(outputBuffer); 273*1b3f573fSAndroid Build Coastguard Worker WriteContext.Initialize(ref span, out WriteContext ctx); 274*1b3f573fSAndroid Build Coastguard Worker for (uint i = 0; i < BytesToWrite / encodedSize; i++) 275*1b3f573fSAndroid Build Coastguard Worker { 276*1b3f573fSAndroid Build Coastguard Worker ctx.WriteRawTag(137, 6); 277*1b3f573fSAndroid Build Coastguard Worker } 278*1b3f573fSAndroid Build Coastguard Worker ctx.Flush(); 279*1b3f573fSAndroid Build Coastguard Worker ctx.CheckNoSpaceLeft(); 280*1b3f573fSAndroid Build Coastguard Worker } 281*1b3f573fSAndroid Build Coastguard Worker 282*1b3f573fSAndroid Build Coastguard Worker [Benchmark] WriteRawTag_ThreeBytes_WriteContext()283*1b3f573fSAndroid Build Coastguard Worker public void WriteRawTag_ThreeBytes_WriteContext() 284*1b3f573fSAndroid Build Coastguard Worker { 285*1b3f573fSAndroid Build Coastguard Worker const int encodedSize = 3; 286*1b3f573fSAndroid Build Coastguard Worker var span = new Span<byte>(outputBuffer); 287*1b3f573fSAndroid Build Coastguard Worker WriteContext.Initialize(ref span, out WriteContext ctx); 288*1b3f573fSAndroid Build Coastguard Worker for (uint i = 0; i < BytesToWrite / encodedSize; i++) 289*1b3f573fSAndroid Build Coastguard Worker { 290*1b3f573fSAndroid Build Coastguard Worker ctx.WriteRawTag(160, 131, 1); 291*1b3f573fSAndroid Build Coastguard Worker } 292*1b3f573fSAndroid Build Coastguard Worker ctx.Flush(); 293*1b3f573fSAndroid Build Coastguard Worker ctx.CheckNoSpaceLeft(); 294*1b3f573fSAndroid Build Coastguard Worker } 295*1b3f573fSAndroid Build Coastguard Worker 296*1b3f573fSAndroid Build Coastguard Worker [Benchmark] Baseline_WriteContext()297*1b3f573fSAndroid Build Coastguard Worker public void Baseline_WriteContext() 298*1b3f573fSAndroid Build Coastguard Worker { 299*1b3f573fSAndroid Build Coastguard Worker var span = new Span<byte>(outputBuffer); 300*1b3f573fSAndroid Build Coastguard Worker WriteContext.Initialize(ref span, out WriteContext ctx); 301*1b3f573fSAndroid Build Coastguard Worker ctx.state.position = outputBuffer.Length; 302*1b3f573fSAndroid Build Coastguard Worker ctx.Flush(); 303*1b3f573fSAndroid Build Coastguard Worker ctx.CheckNoSpaceLeft(); 304*1b3f573fSAndroid Build Coastguard Worker } 305*1b3f573fSAndroid Build Coastguard Worker 306*1b3f573fSAndroid Build Coastguard Worker [Benchmark] WriteRawFloat_CodedOutputStream()307*1b3f573fSAndroid Build Coastguard Worker public void WriteRawFloat_CodedOutputStream() 308*1b3f573fSAndroid Build Coastguard Worker { 309*1b3f573fSAndroid Build Coastguard Worker var cos = new CodedOutputStream(outputBuffer); 310*1b3f573fSAndroid Build Coastguard Worker foreach (var value in floatValues) 311*1b3f573fSAndroid Build Coastguard Worker { 312*1b3f573fSAndroid Build Coastguard Worker cos.WriteFloat(value); 313*1b3f573fSAndroid Build Coastguard Worker } 314*1b3f573fSAndroid Build Coastguard Worker cos.Flush(); 315*1b3f573fSAndroid Build Coastguard Worker cos.CheckNoSpaceLeft(); 316*1b3f573fSAndroid Build Coastguard Worker } 317*1b3f573fSAndroid Build Coastguard Worker 318*1b3f573fSAndroid Build Coastguard Worker [Benchmark] WriteRawFloat_WriteContext()319*1b3f573fSAndroid Build Coastguard Worker public void WriteRawFloat_WriteContext() 320*1b3f573fSAndroid Build Coastguard Worker { 321*1b3f573fSAndroid Build Coastguard Worker var span = new Span<byte>(outputBuffer); 322*1b3f573fSAndroid Build Coastguard Worker WriteContext.Initialize(ref span, out WriteContext ctx); 323*1b3f573fSAndroid Build Coastguard Worker foreach (var value in floatValues) 324*1b3f573fSAndroid Build Coastguard Worker { 325*1b3f573fSAndroid Build Coastguard Worker ctx.WriteFloat(value); 326*1b3f573fSAndroid Build Coastguard Worker } 327*1b3f573fSAndroid Build Coastguard Worker ctx.Flush(); 328*1b3f573fSAndroid Build Coastguard Worker ctx.CheckNoSpaceLeft(); 329*1b3f573fSAndroid Build Coastguard Worker } 330*1b3f573fSAndroid Build Coastguard Worker 331*1b3f573fSAndroid Build Coastguard Worker [Benchmark] WriteRawDouble_CodedOutputStream()332*1b3f573fSAndroid Build Coastguard Worker public void WriteRawDouble_CodedOutputStream() 333*1b3f573fSAndroid Build Coastguard Worker { 334*1b3f573fSAndroid Build Coastguard Worker var cos = new CodedOutputStream(outputBuffer); 335*1b3f573fSAndroid Build Coastguard Worker foreach (var value in doubleValues) 336*1b3f573fSAndroid Build Coastguard Worker { 337*1b3f573fSAndroid Build Coastguard Worker cos.WriteDouble(value); 338*1b3f573fSAndroid Build Coastguard Worker } 339*1b3f573fSAndroid Build Coastguard Worker cos.Flush(); 340*1b3f573fSAndroid Build Coastguard Worker cos.CheckNoSpaceLeft(); 341*1b3f573fSAndroid Build Coastguard Worker } 342*1b3f573fSAndroid Build Coastguard Worker 343*1b3f573fSAndroid Build Coastguard Worker [Benchmark] WriteRawDouble_WriteContext()344*1b3f573fSAndroid Build Coastguard Worker public void WriteRawDouble_WriteContext() 345*1b3f573fSAndroid Build Coastguard Worker { 346*1b3f573fSAndroid Build Coastguard Worker var span = new Span<byte>(outputBuffer); 347*1b3f573fSAndroid Build Coastguard Worker WriteContext.Initialize(ref span, out WriteContext ctx); 348*1b3f573fSAndroid Build Coastguard Worker foreach (var value in doubleValues) 349*1b3f573fSAndroid Build Coastguard Worker { 350*1b3f573fSAndroid Build Coastguard Worker ctx.WriteDouble(value); 351*1b3f573fSAndroid Build Coastguard Worker } 352*1b3f573fSAndroid Build Coastguard Worker ctx.Flush(); 353*1b3f573fSAndroid Build Coastguard Worker ctx.CheckNoSpaceLeft(); 354*1b3f573fSAndroid Build Coastguard Worker } 355*1b3f573fSAndroid Build Coastguard Worker 356*1b3f573fSAndroid Build Coastguard Worker [Benchmark] 357*1b3f573fSAndroid Build Coastguard Worker [ArgumentsSource(nameof(StringEncodedSizes))] WriteString_CodedOutputStream(int encodedSize)358*1b3f573fSAndroid Build Coastguard Worker public void WriteString_CodedOutputStream(int encodedSize) 359*1b3f573fSAndroid Build Coastguard Worker { 360*1b3f573fSAndroid Build Coastguard Worker var values = stringValues[encodedSize]; 361*1b3f573fSAndroid Build Coastguard Worker var cos = new CodedOutputStream(outputBuffer); 362*1b3f573fSAndroid Build Coastguard Worker foreach (var value in values) 363*1b3f573fSAndroid Build Coastguard Worker { 364*1b3f573fSAndroid Build Coastguard Worker cos.WriteString(value); 365*1b3f573fSAndroid Build Coastguard Worker } 366*1b3f573fSAndroid Build Coastguard Worker cos.Flush(); 367*1b3f573fSAndroid Build Coastguard Worker cos.CheckNoSpaceLeft(); 368*1b3f573fSAndroid Build Coastguard Worker } 369*1b3f573fSAndroid Build Coastguard Worker 370*1b3f573fSAndroid Build Coastguard Worker [Benchmark] 371*1b3f573fSAndroid Build Coastguard Worker [ArgumentsSource(nameof(StringEncodedSizes))] WriteString_WriteContext(int encodedSize)372*1b3f573fSAndroid Build Coastguard Worker public void WriteString_WriteContext(int encodedSize) 373*1b3f573fSAndroid Build Coastguard Worker { 374*1b3f573fSAndroid Build Coastguard Worker var values = stringValues[encodedSize]; 375*1b3f573fSAndroid Build Coastguard Worker var span = new Span<byte>(outputBuffer); 376*1b3f573fSAndroid Build Coastguard Worker WriteContext.Initialize(ref span, out WriteContext ctx); 377*1b3f573fSAndroid Build Coastguard Worker foreach (var value in values) 378*1b3f573fSAndroid Build Coastguard Worker { 379*1b3f573fSAndroid Build Coastguard Worker ctx.WriteString(value); 380*1b3f573fSAndroid Build Coastguard Worker } 381*1b3f573fSAndroid Build Coastguard Worker ctx.Flush(); 382*1b3f573fSAndroid Build Coastguard Worker ctx.CheckNoSpaceLeft(); 383*1b3f573fSAndroid Build Coastguard Worker } 384*1b3f573fSAndroid Build Coastguard Worker 385*1b3f573fSAndroid Build Coastguard Worker [Benchmark] 386*1b3f573fSAndroid Build Coastguard Worker [ArgumentsSource(nameof(NonAsciiStringEncodedSizes))] WriteNonAsciiString_CodedOutputStream(int encodedSize)387*1b3f573fSAndroid Build Coastguard Worker public void WriteNonAsciiString_CodedOutputStream(int encodedSize) 388*1b3f573fSAndroid Build Coastguard Worker { 389*1b3f573fSAndroid Build Coastguard Worker var values = nonAsciiStringValues[encodedSize]; 390*1b3f573fSAndroid Build Coastguard Worker var cos = new CodedOutputStream(outputBuffer); 391*1b3f573fSAndroid Build Coastguard Worker foreach (var value in values) 392*1b3f573fSAndroid Build Coastguard Worker { 393*1b3f573fSAndroid Build Coastguard Worker cos.WriteString(value); 394*1b3f573fSAndroid Build Coastguard Worker } 395*1b3f573fSAndroid Build Coastguard Worker cos.Flush(); 396*1b3f573fSAndroid Build Coastguard Worker cos.CheckNoSpaceLeft(); 397*1b3f573fSAndroid Build Coastguard Worker } 398*1b3f573fSAndroid Build Coastguard Worker 399*1b3f573fSAndroid Build Coastguard Worker [Benchmark] 400*1b3f573fSAndroid Build Coastguard Worker [ArgumentsSource(nameof(NonAsciiStringEncodedSizes))] WriteNonAsciiString_WriteContext(int encodedSize)401*1b3f573fSAndroid Build Coastguard Worker public void WriteNonAsciiString_WriteContext(int encodedSize) 402*1b3f573fSAndroid Build Coastguard Worker { 403*1b3f573fSAndroid Build Coastguard Worker var values = nonAsciiStringValues[encodedSize]; 404*1b3f573fSAndroid Build Coastguard Worker var span = new Span<byte>(outputBuffer); 405*1b3f573fSAndroid Build Coastguard Worker WriteContext.Initialize(ref span, out WriteContext ctx); 406*1b3f573fSAndroid Build Coastguard Worker foreach (var value in values) 407*1b3f573fSAndroid Build Coastguard Worker { 408*1b3f573fSAndroid Build Coastguard Worker ctx.WriteString(value); 409*1b3f573fSAndroid Build Coastguard Worker } 410*1b3f573fSAndroid Build Coastguard Worker ctx.Flush(); 411*1b3f573fSAndroid Build Coastguard Worker ctx.CheckNoSpaceLeft(); 412*1b3f573fSAndroid Build Coastguard Worker } 413*1b3f573fSAndroid Build Coastguard Worker 414*1b3f573fSAndroid Build Coastguard Worker [Benchmark] 415*1b3f573fSAndroid Build Coastguard Worker [ArgumentsSource(nameof(StringEncodedSizes))] WriteBytes_CodedOutputStream(int encodedSize)416*1b3f573fSAndroid Build Coastguard Worker public void WriteBytes_CodedOutputStream(int encodedSize) 417*1b3f573fSAndroid Build Coastguard Worker { 418*1b3f573fSAndroid Build Coastguard Worker var values = byteStringValues[encodedSize]; 419*1b3f573fSAndroid Build Coastguard Worker var cos = new CodedOutputStream(outputBuffer); 420*1b3f573fSAndroid Build Coastguard Worker foreach (var value in values) 421*1b3f573fSAndroid Build Coastguard Worker { 422*1b3f573fSAndroid Build Coastguard Worker cos.WriteBytes(value); 423*1b3f573fSAndroid Build Coastguard Worker } 424*1b3f573fSAndroid Build Coastguard Worker cos.Flush(); 425*1b3f573fSAndroid Build Coastguard Worker cos.CheckNoSpaceLeft(); 426*1b3f573fSAndroid Build Coastguard Worker } 427*1b3f573fSAndroid Build Coastguard Worker 428*1b3f573fSAndroid Build Coastguard Worker [Benchmark] 429*1b3f573fSAndroid Build Coastguard Worker [ArgumentsSource(nameof(StringEncodedSizes))] WriteBytes_WriteContext(int encodedSize)430*1b3f573fSAndroid Build Coastguard Worker public void WriteBytes_WriteContext(int encodedSize) 431*1b3f573fSAndroid Build Coastguard Worker { 432*1b3f573fSAndroid Build Coastguard Worker var values = byteStringValues[encodedSize]; 433*1b3f573fSAndroid Build Coastguard Worker var span = new Span<byte>(outputBuffer); 434*1b3f573fSAndroid Build Coastguard Worker WriteContext.Initialize(ref span, out WriteContext ctx); 435*1b3f573fSAndroid Build Coastguard Worker foreach (var value in values) 436*1b3f573fSAndroid Build Coastguard Worker { 437*1b3f573fSAndroid Build Coastguard Worker ctx.WriteBytes(value); 438*1b3f573fSAndroid Build Coastguard Worker } 439*1b3f573fSAndroid Build Coastguard Worker ctx.Flush(); 440*1b3f573fSAndroid Build Coastguard Worker ctx.CheckNoSpaceLeft(); 441*1b3f573fSAndroid Build Coastguard Worker } 442*1b3f573fSAndroid Build Coastguard Worker CreateRandomVarints32(Random random, int valueCount, int encodedSize)443*1b3f573fSAndroid Build Coastguard Worker private static uint[] CreateRandomVarints32(Random random, int valueCount, int encodedSize) 444*1b3f573fSAndroid Build Coastguard Worker { 445*1b3f573fSAndroid Build Coastguard Worker var result = new uint[valueCount]; 446*1b3f573fSAndroid Build Coastguard Worker for (int i = 0; i < valueCount; i++) 447*1b3f573fSAndroid Build Coastguard Worker { 448*1b3f573fSAndroid Build Coastguard Worker result[i] = (uint) ParseRawPrimitivesBenchmark.RandomUnsignedVarint(random, encodedSize, true); 449*1b3f573fSAndroid Build Coastguard Worker } 450*1b3f573fSAndroid Build Coastguard Worker return result; 451*1b3f573fSAndroid Build Coastguard Worker } 452*1b3f573fSAndroid Build Coastguard Worker CreateRandomVarints64(Random random, int valueCount, int encodedSize)453*1b3f573fSAndroid Build Coastguard Worker private static ulong[] CreateRandomVarints64(Random random, int valueCount, int encodedSize) 454*1b3f573fSAndroid Build Coastguard Worker { 455*1b3f573fSAndroid Build Coastguard Worker var result = new ulong[valueCount]; 456*1b3f573fSAndroid Build Coastguard Worker for (int i = 0; i < valueCount; i++) 457*1b3f573fSAndroid Build Coastguard Worker { 458*1b3f573fSAndroid Build Coastguard Worker result[i] = ParseRawPrimitivesBenchmark.RandomUnsignedVarint(random, encodedSize, false); 459*1b3f573fSAndroid Build Coastguard Worker } 460*1b3f573fSAndroid Build Coastguard Worker return result; 461*1b3f573fSAndroid Build Coastguard Worker } 462*1b3f573fSAndroid Build Coastguard Worker CreateRandomFloats(Random random, int valueCount)463*1b3f573fSAndroid Build Coastguard Worker private static float[] CreateRandomFloats(Random random, int valueCount) 464*1b3f573fSAndroid Build Coastguard Worker { 465*1b3f573fSAndroid Build Coastguard Worker var result = new float[valueCount]; 466*1b3f573fSAndroid Build Coastguard Worker for (int i = 0; i < valueCount; i++) 467*1b3f573fSAndroid Build Coastguard Worker { 468*1b3f573fSAndroid Build Coastguard Worker result[i] = (float)random.NextDouble(); 469*1b3f573fSAndroid Build Coastguard Worker } 470*1b3f573fSAndroid Build Coastguard Worker return result; 471*1b3f573fSAndroid Build Coastguard Worker } 472*1b3f573fSAndroid Build Coastguard Worker CreateRandomDoubles(Random random, int valueCount)473*1b3f573fSAndroid Build Coastguard Worker private static double[] CreateRandomDoubles(Random random, int valueCount) 474*1b3f573fSAndroid Build Coastguard Worker { 475*1b3f573fSAndroid Build Coastguard Worker var result = new double[valueCount]; 476*1b3f573fSAndroid Build Coastguard Worker for (int i = 0; i < valueCount; i++) 477*1b3f573fSAndroid Build Coastguard Worker { 478*1b3f573fSAndroid Build Coastguard Worker result[i] = random.NextDouble(); 479*1b3f573fSAndroid Build Coastguard Worker } 480*1b3f573fSAndroid Build Coastguard Worker return result; 481*1b3f573fSAndroid Build Coastguard Worker } 482*1b3f573fSAndroid Build Coastguard Worker CreateStrings(int valueCount, int encodedSize)483*1b3f573fSAndroid Build Coastguard Worker private static string[] CreateStrings(int valueCount, int encodedSize) 484*1b3f573fSAndroid Build Coastguard Worker { 485*1b3f573fSAndroid Build Coastguard Worker var str = ParseRawPrimitivesBenchmark.CreateStringWithEncodedSize(encodedSize); 486*1b3f573fSAndroid Build Coastguard Worker 487*1b3f573fSAndroid Build Coastguard Worker var result = new string[valueCount]; 488*1b3f573fSAndroid Build Coastguard Worker for (int i = 0; i < valueCount; i++) 489*1b3f573fSAndroid Build Coastguard Worker { 490*1b3f573fSAndroid Build Coastguard Worker result[i] = str; 491*1b3f573fSAndroid Build Coastguard Worker } 492*1b3f573fSAndroid Build Coastguard Worker return result; 493*1b3f573fSAndroid Build Coastguard Worker } 494*1b3f573fSAndroid Build Coastguard Worker CreateNonAsciiStrings(int valueCount, int encodedSize)495*1b3f573fSAndroid Build Coastguard Worker private static string[] CreateNonAsciiStrings(int valueCount, int encodedSize) 496*1b3f573fSAndroid Build Coastguard Worker { 497*1b3f573fSAndroid Build Coastguard Worker var str = ParseRawPrimitivesBenchmark.CreateNonAsciiStringWithEncodedSize(encodedSize); 498*1b3f573fSAndroid Build Coastguard Worker 499*1b3f573fSAndroid Build Coastguard Worker var result = new string[valueCount]; 500*1b3f573fSAndroid Build Coastguard Worker for (int i = 0; i < valueCount; i++) 501*1b3f573fSAndroid Build Coastguard Worker { 502*1b3f573fSAndroid Build Coastguard Worker result[i] = str; 503*1b3f573fSAndroid Build Coastguard Worker } 504*1b3f573fSAndroid Build Coastguard Worker return result; 505*1b3f573fSAndroid Build Coastguard Worker } 506*1b3f573fSAndroid Build Coastguard Worker CreateByteStrings(int valueCount, int encodedSize)507*1b3f573fSAndroid Build Coastguard Worker private static ByteString[] CreateByteStrings(int valueCount, int encodedSize) 508*1b3f573fSAndroid Build Coastguard Worker { 509*1b3f573fSAndroid Build Coastguard Worker var str = ParseRawPrimitivesBenchmark.CreateStringWithEncodedSize(encodedSize); 510*1b3f573fSAndroid Build Coastguard Worker 511*1b3f573fSAndroid Build Coastguard Worker var result = new ByteString[valueCount]; 512*1b3f573fSAndroid Build Coastguard Worker for (int i = 0; i < valueCount; i++) 513*1b3f573fSAndroid Build Coastguard Worker { 514*1b3f573fSAndroid Build Coastguard Worker result[i] = ByteString.CopyFrom(Encoding.UTF8.GetBytes(str)); 515*1b3f573fSAndroid Build Coastguard Worker } 516*1b3f573fSAndroid Build Coastguard Worker return result; 517*1b3f573fSAndroid Build Coastguard Worker } 518*1b3f573fSAndroid Build Coastguard Worker } 519*1b3f573fSAndroid Build Coastguard Worker } 520