|
@@ -52,8 +52,13 @@ namespace Google.Protobuf.Benchmarks
|
|
byte[] floatInputBuffer;
|
|
byte[] floatInputBuffer;
|
|
byte[] fixedIntInputBuffer;
|
|
byte[] fixedIntInputBuffer;
|
|
|
|
|
|
|
|
+ // key is the encodedSize of string values
|
|
|
|
+ Dictionary<int, byte[]> stringInputBuffers;
|
|
|
|
+
|
|
Random random = new Random(417384220); // random but deterministic seed
|
|
Random random = new Random(417384220); // random but deterministic seed
|
|
|
|
|
|
|
|
+ public IEnumerable<int> StringEncodedSizes => new[] { 1, 4, 10, 105, 10080 };
|
|
|
|
+
|
|
[GlobalSetup]
|
|
[GlobalSetup]
|
|
public void GlobalSetup()
|
|
public void GlobalSetup()
|
|
{
|
|
{
|
|
@@ -71,6 +76,13 @@ namespace Google.Protobuf.Benchmarks
|
|
doubleInputBuffer = CreateBufferWithRandomDoubles(random, BytesToParse / sizeof(double), paddingValueCount);
|
|
doubleInputBuffer = CreateBufferWithRandomDoubles(random, BytesToParse / sizeof(double), paddingValueCount);
|
|
floatInputBuffer = CreateBufferWithRandomFloats(random, BytesToParse / sizeof(float), paddingValueCount);
|
|
floatInputBuffer = CreateBufferWithRandomFloats(random, BytesToParse / sizeof(float), paddingValueCount);
|
|
fixedIntInputBuffer = CreateBufferWithRandomData(random, BytesToParse / sizeof(long), sizeof(long), paddingValueCount);
|
|
fixedIntInputBuffer = CreateBufferWithRandomData(random, BytesToParse / sizeof(long), sizeof(long), paddingValueCount);
|
|
|
|
+
|
|
|
|
+ stringInputBuffers = new Dictionary<int, byte[]>();
|
|
|
|
+ foreach(var encodedSize in StringEncodedSizes)
|
|
|
|
+ {
|
|
|
|
+ byte[] buffer = CreateBufferWithStrings(BytesToParse / encodedSize, encodedSize, encodedSize < 10 ? 10 : 1 );
|
|
|
|
+ stringInputBuffers.Add(encodedSize, buffer);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
// Total number of bytes that each benchmark will parse.
|
|
// Total number of bytes that each benchmark will parse.
|
|
@@ -262,6 +274,58 @@ namespace Google.Protobuf.Benchmarks
|
|
return sum;
|
|
return sum;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ [Benchmark]
|
|
|
|
+ [ArgumentsSource(nameof(StringEncodedSizes))]
|
|
|
|
+ public int ParseString_CodedInputStream(int encodedSize)
|
|
|
|
+ {
|
|
|
|
+ CodedInputStream cis = new CodedInputStream(stringInputBuffers[encodedSize]);
|
|
|
|
+ int sum = 0;
|
|
|
|
+ for (int i = 0; i < BytesToParse / encodedSize; i++)
|
|
|
|
+ {
|
|
|
|
+ sum += cis.ReadString().Length;
|
|
|
|
+ }
|
|
|
|
+ return sum;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ [Benchmark]
|
|
|
|
+ [ArgumentsSource(nameof(StringEncodedSizes))]
|
|
|
|
+ public int ParseString_ParseContext(int encodedSize)
|
|
|
|
+ {
|
|
|
|
+ InitializeParseContext(stringInputBuffers[encodedSize], out ParseContext ctx);
|
|
|
|
+ int sum = 0;
|
|
|
|
+ for (int i = 0; i < BytesToParse / encodedSize; i++)
|
|
|
|
+ {
|
|
|
|
+ sum += ctx.ReadString().Length;
|
|
|
|
+ }
|
|
|
|
+ return sum;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ [Benchmark]
|
|
|
|
+ [ArgumentsSource(nameof(StringEncodedSizes))]
|
|
|
|
+ public int ParseBytes_CodedInputStream(int encodedSize)
|
|
|
|
+ {
|
|
|
|
+ CodedInputStream cis = new CodedInputStream(stringInputBuffers[encodedSize]);
|
|
|
|
+ int sum = 0;
|
|
|
|
+ for (int i = 0; i < BytesToParse / encodedSize; i++)
|
|
|
|
+ {
|
|
|
|
+ sum += cis.ReadBytes().Length;
|
|
|
|
+ }
|
|
|
|
+ return sum;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ [Benchmark]
|
|
|
|
+ [ArgumentsSource(nameof(StringEncodedSizes))]
|
|
|
|
+ public int ParseBytes_ParseContext(int encodedSize)
|
|
|
|
+ {
|
|
|
|
+ InitializeParseContext(stringInputBuffers[encodedSize], out ParseContext ctx);
|
|
|
|
+ int sum = 0;
|
|
|
|
+ for (int i = 0; i < BytesToParse / encodedSize; i++)
|
|
|
|
+ {
|
|
|
|
+ sum += ctx.ReadBytes().Length;
|
|
|
|
+ }
|
|
|
|
+ return sum;
|
|
|
|
+ }
|
|
|
|
+
|
|
private static void InitializeParseContext(byte[] buffer, out ParseContext ctx)
|
|
private static void InitializeParseContext(byte[] buffer, out ParseContext ctx)
|
|
{
|
|
{
|
|
ParseContext.Initialize(new ReadOnlySequence<byte>(buffer), out ctx);
|
|
ParseContext.Initialize(new ReadOnlySequence<byte>(buffer), out ctx);
|
|
@@ -358,5 +422,40 @@ namespace Google.Protobuf.Benchmarks
|
|
}
|
|
}
|
|
return result;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ private static byte[] CreateBufferWithStrings(int valueCount, int encodedSize, int paddingValueCount)
|
|
|
|
+ {
|
|
|
|
+ var str = CreateStringWithEncodedSize(encodedSize);
|
|
|
|
+
|
|
|
|
+ MemoryStream ms = new MemoryStream();
|
|
|
|
+ CodedOutputStream cos = new CodedOutputStream(ms);
|
|
|
|
+ for (int i = 0; i < valueCount + paddingValueCount; i++)
|
|
|
|
+ {
|
|
|
|
+ cos.WriteString(str);
|
|
|
|
+ }
|
|
|
|
+ cos.Flush();
|
|
|
|
+ var buffer = ms.ToArray();
|
|
|
|
+
|
|
|
|
+ if (buffer.Length != encodedSize * (valueCount + paddingValueCount))
|
|
|
|
+ {
|
|
|
|
+ throw new InvalidOperationException($"Unexpected output buffer length {buffer.Length}");
|
|
|
|
+ }
|
|
|
|
+ return buffer;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private static string CreateStringWithEncodedSize(int encodedSize)
|
|
|
|
+ {
|
|
|
|
+ var str = new string('a', encodedSize);
|
|
|
|
+ while (CodedOutputStream.ComputeStringSize(str) > encodedSize)
|
|
|
|
+ {
|
|
|
|
+ str = str.Substring(1);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (CodedOutputStream.ComputeStringSize(str) != encodedSize)
|
|
|
|
+ {
|
|
|
|
+ throw new InvalidOperationException($"Generated string with wrong encodedSize");
|
|
|
|
+ }
|
|
|
|
+ return str;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|