2
0
mirror of https://github.com/esiur/esiur-dotnet.git synced 2026-06-13 22:48:42 +00:00
This commit is contained in:
2026-06-09 01:40:29 +03:00
parent 2bdd5d5022
commit a741013621
19 changed files with 887 additions and 185 deletions
+178
View File
@@ -0,0 +1,178 @@
using Esiur.Data;
using Esiur.Resource;
using Google.Protobuf;
using System.Diagnostics;
using System.Text.Json;
using System.Text.Json.Serialization;
using EsiurModel = Esiur.Tests.RPC.EsiurServer;
using GrpcModel = Esiur.Tests.RPC.Client.Grpc;
using SharedModel = Esiur.Tests.RPC.Client.SharedModel;
namespace Esiur.Tests.RPC.Client;
public sealed record SerializationSample(
int Round,
int Seed,
string Protocol,
string Category,
string Workload,
long PayloadBytes,
double SerializeMs,
double DeserializeMs);
public static class SerializationExperiment
{
private static readonly JsonSerializerOptions JsonOptions = new()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};
public static List<SerializationSample> RunRound(
int round,
int seed,
Dictionary<string, EsiurModel.BusinessDocument[]> docsWorkloads,
Dictionary<string, byte[]> dataWorkloads,
Dictionary<string, int[]> intWorkloads,
int iterations)
{
if (iterations <= 0)
throw new ArgumentOutOfRangeException(nameof(iterations));
EsiurModel.Initialization.RegisterTypes(Warehouse.Default);
var samples = new List<SerializationSample>();
foreach (var workload in docsWorkloads)
{
var docs = workload.Value;
var grpcDocs = docs.Select(x => x.ToGrpc()).ToArray();
var sharedDocs = docs.Select(x => x.ToShared()).ToArray();
samples.Add(Measure(
round, seed, "esiur", "Docs", workload.Key, iterations,
() => Codec.Compose(docs, Warehouse.Default, null),
payload => GC.KeepAlive(Codec.ParseSync(payload, 0, Warehouse.Default).Item2)));
samples.Add(Measure(
round, seed, "grpc", "Docs", workload.Key, iterations,
() =>
{
var request = new GrpcModel.DocumentsRequest();
request.Docs.AddRange(grpcDocs);
return request.ToByteArray();
},
payload => GC.KeepAlive(GrpcModel.DocumentsRequest.Parser.ParseFrom(payload))));
samples.Add(Measure(
round, seed, "json", "Docs", workload.Key, iterations,
() => JsonSerializer.SerializeToUtf8Bytes(docs, JsonOptions),
payload => GC.KeepAlive(JsonSerializer.Deserialize<EsiurModel.BusinessDocument[]>(payload, JsonOptions))));
samples.Add(Measure(
round, seed, "signalr", "Docs", workload.Key, iterations,
() => JsonSerializer.SerializeToUtf8Bytes(sharedDocs, JsonOptions),
payload => GC.KeepAlive(JsonSerializer.Deserialize<SharedModel.BusinessDocument[]>(payload, JsonOptions))));
}
foreach (var workload in dataWorkloads)
{
var data = workload.Value;
samples.Add(Measure(
round, seed, "esiur", "Bytes", workload.Key, iterations,
() => Codec.Compose(data, Warehouse.Default, null),
payload => GC.KeepAlive(Codec.ParseSync(payload, 0, Warehouse.Default).Item2)));
samples.Add(Measure(
round, seed, "grpc", "Bytes", workload.Key, iterations,
() => new GrpcModel.BytesRequest { Data = ByteString.CopyFrom(data) }.ToByteArray(),
payload => GC.KeepAlive(GrpcModel.BytesRequest.Parser.ParseFrom(payload))));
samples.Add(Measure(
round, seed, "json", "Bytes", workload.Key, iterations,
() => JsonSerializer.SerializeToUtf8Bytes(data, JsonOptions),
payload => GC.KeepAlive(JsonSerializer.Deserialize<byte[]>(payload, JsonOptions))));
samples.Add(Measure(
round, seed, "signalr", "Bytes", workload.Key, iterations,
() => JsonSerializer.SerializeToUtf8Bytes(data, JsonOptions),
payload => GC.KeepAlive(JsonSerializer.Deserialize<byte[]>(payload, JsonOptions))));
}
foreach (var workload in intWorkloads)
{
var data = workload.Value;
samples.Add(Measure(
round, seed, "esiur", "Ints", workload.Key, iterations,
() => Codec.Compose(data, Warehouse.Default, null),
payload => GC.KeepAlive(Codec.ParseSync(payload, 0, Warehouse.Default).Item2)));
samples.Add(Measure(
round, seed, "grpc", "Ints", workload.Key, iterations,
() =>
{
var request = new GrpcModel.IntArrayRequest();
request.Array.AddRange(data);
return request.ToByteArray();
},
payload => GC.KeepAlive(GrpcModel.IntArrayRequest.Parser.ParseFrom(payload))));
samples.Add(Measure(
round, seed, "json", "Ints", workload.Key, iterations,
() => JsonSerializer.SerializeToUtf8Bytes(data, JsonOptions),
payload => GC.KeepAlive(JsonSerializer.Deserialize<int[]>(payload, JsonOptions))));
samples.Add(Measure(
round, seed, "signalr", "Ints", workload.Key, iterations,
() => JsonSerializer.SerializeToUtf8Bytes(data, JsonOptions),
payload => GC.KeepAlive(JsonSerializer.Deserialize<int[]>(payload, JsonOptions))));
}
return samples;
}
private static SerializationSample Measure(
int round,
int seed,
string protocol,
string category,
string workload,
int iterations,
Func<byte[]> serialize,
Action<byte[]> deserialize)
{
var payload = serialize();
deserialize(payload);
long payloadBytes = payload.Length;
long serializeTicks = 0;
long deserializeTicks = 0;
for (var i = 0; i < iterations; i++)
{
var started = Stopwatch.GetTimestamp();
payload = serialize();
serializeTicks += Stopwatch.GetTimestamp() - started;
payloadBytes = payload.Length;
started = Stopwatch.GetTimestamp();
deserialize(payload);
deserializeTicks += Stopwatch.GetTimestamp() - started;
}
return new SerializationSample(
round,
seed,
protocol,
category,
workload,
payloadBytes,
TicksToMs(serializeTicks) / iterations,
TicksToMs(deserializeTicks) / iterations);
}
private static double TicksToMs(long ticks)
=> ticks * 1000.0 / Stopwatch.Frequency;
}