Skip to content

Commit 03fcf95

Browse files
committed
"Improve LogEventBenchmark benchmarks":
1 parent 1c77935 commit 03fcf95

File tree

2 files changed

+91
-41
lines changed

2 files changed

+91
-41
lines changed

src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLogger.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,10 @@ LogEvent PrepareWrite<TState>(LogEventLevel level, EventId eventId, TState state
115115
}
116116
else
117117
{
118-
if (_logger.BindProperty(property.Key, property.Value, false, out var bound))
118+
// Simple micro-optimization for the most common and reliably scalar values; could go further here.
119+
if (property.Value is null or string or int or long && LogEventProperty.IsValidName(property.Key))
120+
properties.Add(property.Key, new ScalarValue(property.Value));
121+
else if (_logger.BindProperty(property.Key, property.Value, false, out var bound))
119122
properties.Add(bound.Name, bound.Value);
120123
}
121124
}
@@ -154,7 +157,7 @@ LogEvent PrepareWrite<TState>(LogEventLevel level, EventId eventId, TState state
154157
}
155158
}
156159

157-
if (eventId.Id != 0 || eventId.Name != null)
160+
if (eventId != default)
158161
properties.Add("EventId", CreateEventIdPropertyValue(eventId));
159162

160163
var (traceId, spanId) = Activity.Current is { } activity ?

test/Serilog.Extensions.Logging.Benchmarks/LogEventBenchmark.cs

Lines changed: 86 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -20,46 +20,93 @@
2020

2121
#pragma warning disable xUnit1013 // Public method should be marked as test
2222

23-
namespace Serilog.Extensions.Logging.Benchmarks
23+
namespace Serilog.Extensions.Logging.Benchmarks;
24+
25+
[MemoryDiagnoser]
26+
public class LogEventBenchmark
2427
{
25-
[MemoryDiagnoser]
26-
public class LogEventBenchmark
28+
class Person
29+
{
30+
public string? Name { get; set; }
31+
public int Age { get; set; }
32+
public override string ToString() => "Fixed text";
33+
}
34+
35+
readonly IMelLogger _melLogger;
36+
readonly Person _bob, _alice;
37+
readonly ILogger _underlyingLogger;
38+
39+
public LogEventBenchmark()
40+
{
41+
_underlyingLogger = new LoggerConfiguration().CreateLogger();
42+
_melLogger = new SerilogLoggerProvider(_underlyingLogger).CreateLogger(GetType().FullName!);
43+
_bob = new Person { Name = "Bob", Age = 42 };
44+
_alice = new Person { Name = "Alice", Age = 42 };
45+
}
46+
47+
[Fact]
48+
public void Benchmark()
49+
{
50+
BenchmarkRunner.Run<LogEventBenchmark>();
51+
}
52+
53+
[Benchmark(Baseline = true)]
54+
public void SerilogOnly()
55+
{
56+
_underlyingLogger.Information("Hello!");
57+
}
58+
59+
[Benchmark]
60+
public void SimpleEvent()
61+
{
62+
_melLogger.LogInformation("Hello!");
63+
}
64+
65+
[Benchmark]
66+
public void Template()
67+
{
68+
_melLogger.LogInformation("Hello, {Property1}!", 42);
69+
}
70+
71+
[Benchmark]
72+
public void StringScope()
73+
{
74+
using var scope = _melLogger.BeginScope("Scope1");
75+
_melLogger.LogInformation("Hello!");
76+
}
77+
78+
[Benchmark]
79+
public void TemplateScope()
80+
{
81+
using var scope = _melLogger.BeginScope("Scope1 {Property1}", 42);
82+
_melLogger.LogInformation("Hello!");
83+
}
84+
85+
[Benchmark]
86+
public void TupleScope()
87+
{
88+
using var scope = _melLogger.BeginScope(("Property1", 42));
89+
_melLogger.LogInformation("Hello!");
90+
}
91+
92+
[Benchmark]
93+
public void DictionaryScope()
94+
{
95+
// Note that allocations here include the dictionary and boxed int.
96+
using var scope = _melLogger.BeginScope(new Dictionary<string, object> { ["Property1"] = 42 });
97+
_melLogger.LogInformation("Hello!");
98+
}
99+
100+
[Benchmark]
101+
public void Capturing()
102+
{
103+
_melLogger.LogInformation("Hi {@User} from {$Me}", _bob, _alice);
104+
}
105+
106+
[Benchmark]
107+
public void CapturingScope()
27108
{
28-
class Person
29-
{
30-
public string? Name { get; set; }
31-
public int Age { get; set; }
32-
public override string ToString() => "Fixed text";
33-
}
34-
35-
readonly IMelLogger _melLogger;
36-
readonly Person _bob, _alice;
37-
38-
public LogEventBenchmark()
39-
{
40-
var underlyingLogger = new LoggerConfiguration().CreateLogger();
41-
_melLogger = new SerilogLoggerProvider(underlyingLogger).CreateLogger(GetType().FullName!);
42-
_bob = new Person { Name = "Bob", Age = 42 };
43-
_alice = new Person { Name = "Alice", Age = 42 };
44-
}
45-
46-
[Fact]
47-
public void Benchmark()
48-
{
49-
BenchmarkRunner.Run<LogEventBenchmark>();
50-
}
51-
52-
[Benchmark]
53-
public void LogInformation()
54-
{
55-
_melLogger.LogInformation("Hi {@User} from {$Me}", _bob, _alice);
56-
}
57-
58-
[Benchmark]
59-
public void LogInformationScoped()
60-
{
61-
using var scope = _melLogger.BeginScope("Hi {@User} from {$Me}", _bob, _alice);
62-
_melLogger.LogInformation("Hi");
63-
}
109+
using var scope = _melLogger.BeginScope("Hi {@User} from {$Me}", _bob, _alice);
110+
_melLogger.LogInformation("Hi");
64111
}
65112
}

0 commit comments

Comments
 (0)