// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// ------------------------------------------------------------
namespace Microsoft.Azure.Cosmos.Serialization.HybridRow.Tests.Perf
{
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Azure.Cosmos.Core.Utf8;
using Microsoft.Azure.Cosmos.Serialization.HybridRow.Layouts;
using Microsoft.VisualStudio.TestTools.UnitTesting;
///
/// Tests involving generated (early bound) code compiled from schema based on a partial implementation
/// of Cassandra Hotel Schema described here: https://www.oreilly.com/ideas/cassandra-data-modeling .
///
/// The tests here differ from in that they rely on
/// the schema being known at compile time instead of runtime. This allows code to be generated that
/// directly addresses the schema structure instead of dynamically discovering schema structure at
/// runtime.
///
///
[TestClass]
public sealed class CodeGenMicroBenchmarkSuite : MicroBenchmarkSuiteBase
{
private const int GuestCount = 1000;
private const int HotelCount = 10000;
private const int RoomsCount = 10000;
[TestMethod]
[Owner("jthunter")]
[DeploymentItem(TestData.GuestsExpected, TestData.Target)]
public async Task ProtobufGuestsWriteBenchmarkAsync()
{
string expectedFile = TestData.GuestsExpected;
(List> expected, LayoutResolverNamespace _) = await this.LoadExpectedAsync(expectedFile);
CodeGenMicroBenchmarkSuite.ProtobufWriteBenchmark("Guests", "Guests", CodeGenMicroBenchmarkSuite.GuestCount, expected);
}
[TestMethod]
[Owner("jthunter")]
[DeploymentItem(TestData.HotelExpected, TestData.Target)]
public async Task ProtobufHotelWriteBenchmarkAsync()
{
string expectedFile = TestData.HotelExpected;
(List> expected, LayoutResolverNamespace _) = await this.LoadExpectedAsync(expectedFile);
CodeGenMicroBenchmarkSuite.ProtobufWriteBenchmark("Hotels", "Hotels", CodeGenMicroBenchmarkSuite.HotelCount, expected);
}
[TestMethod]
[Owner("jthunter")]
[DeploymentItem(TestData.RoomsExpected, TestData.Target)]
public async Task ProtobufRoomsWriteBenchmarkAsync()
{
string expectedFile = TestData.RoomsExpected;
(List> expected, LayoutResolverNamespace _) = await this.LoadExpectedAsync(expectedFile);
CodeGenMicroBenchmarkSuite.ProtobufWriteBenchmark(
"Available_Rooms_By_Hotel_Date",
"Rooms",
CodeGenMicroBenchmarkSuite.RoomsCount,
expected);
}
[TestMethod]
[Owner("jthunter")]
[DeploymentItem(TestData.GuestsExpected, TestData.Target)]
public async Task ProtobufGuestsReadBenchmarkAsync()
{
string expectedFile = TestData.GuestsExpected;
(List> expected, LayoutResolverNamespace _) = await this.LoadExpectedAsync(expectedFile);
CodeGenMicroBenchmarkSuite.ProtobufReadBenchmark("Guests", "Guests", CodeGenMicroBenchmarkSuite.GuestCount, expected);
}
[TestMethod]
[Owner("jthunter")]
[DeploymentItem(TestData.HotelExpected, TestData.Target)]
public async Task ProtobufHotelReadBenchmarkAsync()
{
string expectedFile = TestData.HotelExpected;
(List> expected, LayoutResolverNamespace _) = await this.LoadExpectedAsync(expectedFile);
CodeGenMicroBenchmarkSuite.ProtobufReadBenchmark("Hotels", "Hotels", CodeGenMicroBenchmarkSuite.HotelCount, expected);
}
[TestMethod]
[Owner("jthunter")]
[DeploymentItem(TestData.RoomsExpected, TestData.Target)]
public async Task ProtobufRoomsReadBenchmarkAsync()
{
string expectedFile = TestData.RoomsExpected;
(List> expected, LayoutResolverNamespace _) = await this.LoadExpectedAsync(expectedFile);
CodeGenMicroBenchmarkSuite.ProtobufReadBenchmark(
"Available_Rooms_By_Hotel_Date",
"Rooms",
CodeGenMicroBenchmarkSuite.RoomsCount,
expected);
}
[TestMethod]
[Owner("jthunter")]
[DeploymentItem(TestData.GuestsExpected, TestData.Target)]
public async Task CodeGenGuestsWriteBenchmarkAsync()
{
string expectedFile = TestData.GuestsExpected;
(List> expected, LayoutResolverNamespace resolver) = await this.LoadExpectedAsync(expectedFile);
CodeGenMicroBenchmarkSuite.CodeGenWriteBenchmark(resolver, "Guests", "Guests", CodeGenMicroBenchmarkSuite.GuestCount, expected);
}
[TestMethod]
[Owner("jthunter")]
[DeploymentItem(TestData.HotelExpected, TestData.Target)]
public async Task CodeGenHotelWriteBenchmarkAsync()
{
string expectedFile = TestData.HotelExpected;
(List> expected, LayoutResolverNamespace resolver) = await this.LoadExpectedAsync(expectedFile);
CodeGenMicroBenchmarkSuite.CodeGenWriteBenchmark(resolver, "Hotels", "Hotels", CodeGenMicroBenchmarkSuite.HotelCount, expected);
}
[TestMethod]
[Owner("jthunter")]
[DeploymentItem(TestData.RoomsExpected, TestData.Target)]
public async Task CodeGenRoomsWriteBenchmarkAsync()
{
string expectedFile = TestData.RoomsExpected;
(List> expected, LayoutResolverNamespace resolver) = await this.LoadExpectedAsync(expectedFile);
CodeGenMicroBenchmarkSuite.CodeGenWriteBenchmark(
resolver,
"Available_Rooms_By_Hotel_Date",
"Rooms",
CodeGenMicroBenchmarkSuite.RoomsCount,
expected);
}
[TestMethod]
[Owner("jthunter")]
[DeploymentItem(TestData.GuestsExpected, TestData.Target)]
public async Task CodeGenGuestsReadBenchmarkAsync()
{
string expectedFile = TestData.GuestsExpected;
(List> expected, LayoutResolverNamespace resolver) = await this.LoadExpectedAsync(expectedFile);
CodeGenMicroBenchmarkSuite.CodeGenReadBenchmark(resolver, "Guests", "Guests", CodeGenMicroBenchmarkSuite.GuestCount, expected);
}
[TestMethod]
[Owner("jthunter")]
[DeploymentItem(TestData.HotelExpected, TestData.Target)]
public async Task CodeGenHotelReadBenchmarkAsync()
{
string expectedFile = TestData.HotelExpected;
(List> expected, LayoutResolverNamespace resolver) = await this.LoadExpectedAsync(expectedFile);
CodeGenMicroBenchmarkSuite.CodeGenReadBenchmark(resolver, "Hotels", "Hotels", CodeGenMicroBenchmarkSuite.HotelCount, expected);
}
[TestMethod]
[Owner("jthunter")]
[DeploymentItem(TestData.RoomsExpected, TestData.Target)]
public async Task CodeGenRoomsReadBenchmarkAsync()
{
string expectedFile = TestData.RoomsExpected;
(List> expected, LayoutResolverNamespace resolver) = await this.LoadExpectedAsync(expectedFile);
CodeGenMicroBenchmarkSuite.CodeGenReadBenchmark(
resolver,
"Available_Rooms_By_Hotel_Date",
"Rooms",
CodeGenMicroBenchmarkSuite.RoomsCount,
expected);
}
private static void ProtobufWriteBenchmark(
string schemaName,
string dataSetName,
int innerLoopIterations,
List> expected)
{
BenchmarkContext context = new BenchmarkContext
{
ProtobufWriter = new ProtobufRowGenerator(schemaName, BenchmarkSuiteBase.InitialCapacity)
};
MicroBenchmarkSuiteBase.Benchmark(
"CodeGen",
"Write",
dataSetName,
"Protobuf",
innerLoopIterations,
ref context,
(ref BenchmarkContext ctx, Dictionary tableValue) => { ctx.ProtobufWriter.WriteBuffer(tableValue); },
(ref BenchmarkContext ctx, Dictionary tableValue) => ctx.ProtobufWriter.Length,
expected);
}
private static void ProtobufReadBenchmark(
string schemaName,
string dataSetName,
int innerLoopIterations,
List> expected)
{
// Serialize input data to sequence of byte buffers.
List expectedSerialized = new List(expected.Count);
BenchmarkContext context = new BenchmarkContext
{
ProtobufWriter = new ProtobufRowGenerator(schemaName, BenchmarkSuiteBase.InitialCapacity)
};
foreach (Dictionary tableValue in expected)
{
context.ProtobufWriter.WriteBuffer(tableValue);
expectedSerialized.Add(context.ProtobufWriter.ToArray());
}
MicroBenchmarkSuiteBase.Benchmark(
"CodeGen",
"Read",
dataSetName,
"Protobuf",
innerLoopIterations,
ref context,
(ref BenchmarkContext ctx, byte[] tableValue) => ctx.ProtobufWriter.ReadBuffer(tableValue),
(ref BenchmarkContext ctx, byte[] tableValue) => tableValue.Length,
expectedSerialized);
}
private static void CodeGenWriteBenchmark(
LayoutResolverNamespace resolver,
string schemaName,
string dataSetName,
int innerLoopIterations,
List> expected)
{
Layout layout = resolver.Resolve(resolver.Namespace.Schemas.Find(x => x.Name == schemaName).SchemaId);
BenchmarkContext context = new BenchmarkContext
{
CodeGenWriter = new CodeGenRowGenerator(BenchmarkSuiteBase.InitialCapacity, layout, resolver)
};
MicroBenchmarkSuiteBase.Benchmark(
"CodeGen",
"Write",
dataSetName,
"HybridRowGen",
innerLoopIterations,
ref context,
(ref BenchmarkContext ctx, Dictionary tableValue) =>
{
ctx.CodeGenWriter.Reset();
Result r = ctx.CodeGenWriter.WriteBuffer(tableValue);
ResultAssert.IsSuccess(r);
},
(ref BenchmarkContext ctx, Dictionary tableValue) => ctx.CodeGenWriter.Length,
expected);
}
private static void CodeGenReadBenchmark(
LayoutResolverNamespace resolver,
string schemaName,
string dataSetName,
int innerLoopIterations,
List> expected)
{
// Serialize input data to sequence of byte buffers.
List expectedSerialized = new List(expected.Count);
Layout layout = resolver.Resolve(resolver.Namespace.Schemas.Find(x => x.Name == schemaName).SchemaId);
BenchmarkContext context = new BenchmarkContext
{
CodeGenWriter = new CodeGenRowGenerator(BenchmarkSuiteBase.InitialCapacity, layout, resolver)
};
foreach (Dictionary tableValue in expected)
{
context.CodeGenWriter.Reset();
Result r = context.CodeGenWriter.WriteBuffer(tableValue);
ResultAssert.IsSuccess(r);
expectedSerialized.Add(context.CodeGenWriter.ToArray());
}
MicroBenchmarkSuiteBase.Benchmark(
"CodeGen",
"Read",
dataSetName,
"HybridRowGen",
innerLoopIterations,
ref context,
(ref BenchmarkContext ctx, byte[] tableValue) =>
{
Result r = ctx.CodeGenWriter.ReadBuffer(tableValue);
ResultAssert.IsSuccess(r);
},
(ref BenchmarkContext ctx, byte[] tableValue) => tableValue.Length,
expectedSerialized);
}
}
}