Skip to content

Commit 13de60b

Browse files
committed
add benchmarks
1 parent bd5f794 commit 13de60b

1 file changed

Lines changed: 139 additions & 0 deletions

File tree

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
// Copyright The OpenTelemetry Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
extern alias OpenTelemetryProtocol;
5+
6+
using BenchmarkDotNet.Attributes;
7+
using Benchmarks.Helper;
8+
using OpenTelemetry.Logs;
9+
using OpenTelemetryProtocol::OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation;
10+
using OpenTelemetryProtocol::OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation.Serializer;
11+
12+
/*
13+
BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.8457/25H2/2025Update/HudsonValley2)
14+
AMD Ryzen 7 9800X3D 4.70GHz, 1 CPU, 16 logical and 8 physical cores
15+
.NET SDK 10.0.301
16+
[Host] : .NET 10.0.9 (10.0.9, 10.0.926.27113), X64 RyuJIT x86-64-v4
17+
DefaultJob : .NET 10.0.9 (10.0.9, 10.0.926.27113), X64 RyuJIT x86-64-v4
18+
19+
20+
| Method | AttributeCount | KvListAttributeCount | Mean | Error | StdDev | Median | Allocated |
21+
|--------------- |--------------- |--------------------- |---------:|---------:|---------:|---------:|----------:|
22+
| WriteLogRecord | 4 | 0 | 113.8 ns | 1.87 ns | 1.57 ns | 113.9 ns | 32 B |
23+
| WriteLogRecord | 4 | 2 | 168.9 ns | 3.15 ns | 8.31 ns | 166.4 ns | 32 B |
24+
| WriteLogRecord | 4 | 4 | 224.2 ns | 4.55 ns | 12.84 ns | 219.1 ns | 32 B |
25+
| WriteLogRecord | 4 | 8 | 254.4 ns | 5.11 ns | 10.99 ns | 252.6 ns | 32 B |
26+
| WriteLogRecord | 8 | 0 | 193.0 ns | 3.88 ns | 9.58 ns | 188.7 ns | 32 B |
27+
| WriteLogRecord | 8 | 2 | 239.4 ns | 2.89 ns | 2.26 ns | 239.3 ns | 32 B |
28+
| WriteLogRecord | 8 | 4 | 297.5 ns | 5.87 ns | 10.58 ns | 294.2 ns | 32 B |
29+
| WriteLogRecord | 8 | 8 | 340.9 ns | 8.21 ns | 23.03 ns | 332.2 ns | 32 B |
30+
| WriteLogRecord | 16 | 0 | 365.1 ns | 7.95 ns | 22.16 ns | 357.4 ns | 32 B |
31+
| WriteLogRecord | 16 | 2 | 427.9 ns | 11.96 ns | 34.70 ns | 417.5 ns | 32 B |
32+
| WriteLogRecord | 16 | 4 | 476.7 ns | 15.13 ns | 44.62 ns | 480.0 ns | 32 B |
33+
| WriteLogRecord | 16 | 8 | 471.3 ns | 9.11 ns | 12.16 ns | 466.0 ns | 32 B |
34+
*/
35+
36+
namespace Benchmarks.Exporter;
37+
38+
[MemoryDiagnoser(false)]
39+
public class ProtobufOtlpLogSerializerBenchmarks
40+
{
41+
private static readonly KeyValuePair<string, object?>[] AllAttributes =
42+
[
43+
new("http.request.method", "GET"),
44+
new("http.route", "/api/orders/{id}"),
45+
new("http.response.status_code", 200L),
46+
new("url.full", "https://shop.example.com/api/orders/42"),
47+
new("url.scheme", "https"),
48+
new("server.address", "shop.example.com"),
49+
new("server.port", 443L),
50+
new("client.address", "203.0.113.7"),
51+
new("user_agent.original", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)"),
52+
new("network.protocol.version", "1.1"),
53+
new("enduser.id", "user-8f3a7b4c"),
54+
new("session.id", "9a8d1f3e-4b2c-4e15-9a4f-1b2c3d4e5f6a"),
55+
new("db.system", "postgresql"),
56+
new("db.namespace", "orders"),
57+
new("db.operation.name", "SELECT"),
58+
new("db.query.text", "SELECT * FROM orders WHERE id = $1"),
59+
new("messaging.system", "rabbitmq"),
60+
new("messaging.destination.name", "orders.events"),
61+
new("messaging.message.id", "msg-0abcdef1234567890"),
62+
new("exception.type", "System.TimeoutException"),
63+
new("exception.message", "The operation has timed out."),
64+
new("code.function", "ProcessOrder"),
65+
new("code.namespace", "Checkout.Api.Orders"),
66+
new("code.filepath", "/src/Checkout.Api/Orders/OrderProcessor.cs"),
67+
new("code.lineno", 142L),
68+
new("thread.id", 27L),
69+
new("thread.name", "worker-3"),
70+
new("retry.count", 2L),
71+
new("cache.hit", true),
72+
new("response.latency_ms", 18.7),
73+
new("feature.flag.new_checkout", true),
74+
new("tenant.id", "tenant-123456789012"),
75+
];
76+
77+
private readonly byte[] buffer = new byte[64 * 1024];
78+
private readonly SdkLimitOptions sdkLimitOptions = new();
79+
private readonly ExperimentalOptions experimentalOptions = new();
80+
private LogRecord logRecord = null!;
81+
82+
[Params(4, 8, 16)]
83+
public int AttributeCount { get; set; }
84+
85+
// 0 means no kvlist attribute is added; otherwise a single flat (depth-1)
86+
// kvlist attribute with this many entries is appended to the scalar ones.
87+
[Params(0, 2, 4, 8)]
88+
public int KvListAttributeCount { get; set; }
89+
90+
[GlobalSetup]
91+
public void Setup()
92+
{
93+
this.logRecord = LogRecordHelper.CreateTestLogRecord();
94+
95+
var includeKvList = this.KvListAttributeCount > 0;
96+
var attributes = new KeyValuePair<string, object?>[this.AttributeCount + (includeKvList ? 1 : 0)];
97+
98+
var count = Math.Min(this.AttributeCount, AllAttributes.Length);
99+
for (var i = 0; i < count; i++)
100+
{
101+
attributes[i] = AllAttributes[i];
102+
}
103+
104+
for (var i = count; i < this.AttributeCount; i++)
105+
{
106+
attributes[i] = new KeyValuePair<string, object?>($"custom.attribute.{i}", Guid.NewGuid().ToString());
107+
}
108+
109+
if (includeKvList)
110+
{
111+
attributes[this.AttributeCount] = new KeyValuePair<string, object?>("kvlist", BuildKvList(this.KvListAttributeCount));
112+
}
113+
114+
this.logRecord.Attributes = attributes;
115+
}
116+
117+
[Benchmark]
118+
public int WriteLogRecord()
119+
=> ProtobufOtlpLogSerializer.WriteLogRecord(this.buffer, 0, this.sdkLimitOptions, this.experimentalOptions, this.logRecord);
120+
121+
private static List<KeyValuePair<string, object?>> BuildKvList(int entryCount)
122+
{
123+
var list = new List<KeyValuePair<string, object?>>(entryCount);
124+
for (var i = 0; i < entryCount; i++)
125+
{
126+
object value = (i % 4) switch
127+
{
128+
0 => "value",
129+
1 => (long)i,
130+
2 => i % 2 == 0,
131+
_ => i * 1.5,
132+
};
133+
134+
list.Add(new KeyValuePair<string, object?>($"key.{i}", value));
135+
}
136+
137+
return list;
138+
}
139+
}

0 commit comments

Comments
 (0)