Skip to content

Instantly share code, notes, and snippets.

@gingters
Last active December 16, 2021 14:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gingters/476f258e5e91f093902e1620358e49fd to your computer and use it in GitHub Desktop.
Save gingters/476f258e5e91f093902e1620358e49fd to your computer and use it in GitHub Desktop.
Logging Performance Benchmark (.NET 6 console test)
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.13.1" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
</ItemGroup>
</Project>
/*
Run with
dotnet run --configuration=RELEASE
*/
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
BenchmarkRunner.Run<LoggingClass>();
record CustomData(string SomeText, int SomeValue, DateTime SomeDate);
[MemoryDiagnoser]
public partial class LoggingClass
{
private readonly ILogger _logger;
private readonly CustomData _customData;
public LoggingClass()
: this(
new ServiceCollection()
.AddLogging(o => o
.SetMinimumLevel(LogLevel.Information)
.AddProvider(new NullLoggerProvider())
)
.BuildServiceProvider()
.GetRequiredService<ILogger<LoggingClass>>()
)
{ }
public LoggingClass(ILogger<LoggingClass> logger)
{
_logger = logger;
_customData = new CustomData("SomeText", 1, DateTime.UtcNow);
}
// INTERPOLATED LOGGING USAGE
[Benchmark]
public void InterpolatedLogTrace()
{
_logger.LogTrace(1, $"This is a sample template logging {_customData.SomeText} {_customData.SomeValue} {_customData.SomeDate} All: @{_customData}");
}
[Benchmark]
public void InterpolatedLogCritical()
{
_logger.LogCritical(1, $"This is a sample template logging {_customData.SomeText} {_customData.SomeValue} {_customData.SomeDate} All: @{_customData}");
}
// CHECKED INTERPOLATED LOGGING USAGE
[Benchmark]
public void CheckedInterpolatedLogTrace()
{
if (_logger.IsEnabled(LogLevel.Trace))
{
_logger.LogTrace(1, $"This is a sample template logging {_customData.SomeText} {_customData.SomeValue} {_customData.SomeDate} All: @{_customData}");
}
}
[Benchmark]
public void CheckedInterpolatedLogCritical()
{
if (_logger.IsEnabled(LogLevel.Critical))
{
_logger.LogCritical(1, $"This is a sample template logging {_customData.SomeText} {_customData.SomeValue} {_customData.SomeDate} All: @{_customData}");
}
}
// COMMON LOGGING USAGE
[Benchmark]
public void CommonLoggingTrace()
{
_logger.LogTrace(1, "This is a sample template logging {Text} {Value} {Date} All: @{data}", _customData.SomeText, _customData.SomeValue, _customData.SomeDate, _customData);
}
[Benchmark]
public void CommonLoggingCritical()
{
_logger.LogCritical(1, "This is a sample template logging {Text} {Value} {Date} All: @{data}", _customData.SomeText, _customData.SomeValue, _customData.SomeDate, _customData);
}
// LOG LEVEL CHECKED LOGGING USAGE
[Benchmark]
public void CheckedCommonLoggingTrace()
{
if (_logger.IsEnabled(LogLevel.Trace))
{
_logger.LogTrace(1, "This is a sample template logging {Text} {Value} {Date} All: @{data}", _customData.SomeText, _customData.SomeValue, _customData.SomeDate, _customData);
}
}
[Benchmark]
public void CheckedCommonLoggingCritical()
{
if (_logger.IsEnabled(LogLevel.Critical))
{
_logger.LogCritical(1, "This is a sample template logging {Text} {Value} {Date} All: @{data}", _customData.SomeText, _customData.SomeValue, _customData.SomeDate, _customData);
}
}
// DEFINED ACTION LOGGING USAGE
private static readonly Action<ILogger, string, int, DateTime, CustomData, Exception?> _logActionTrace =
LoggerMessage.Define<string, int, DateTime, CustomData>(
logLevel: LogLevel.Trace,
eventId: 1,
formatString: "This is a sample template logging {Text} {Value} {Date} All: @{data}");
private static readonly Action<ILogger, string, int, DateTime, CustomData, Exception?> _logActionCritical =
LoggerMessage.Define<string, int, DateTime, CustomData>(
logLevel: LogLevel.Critical,
eventId: 1,
formatString: "This is a sample template logging {Text} {Value} {Date} All: @{data}");
[Benchmark]
public void ActionLoggingTrace()
{
_logActionTrace(_logger, _customData.SomeText, _customData.SomeValue, _customData.SomeDate, _customData, null);
}
[Benchmark]
public void ActionLoggingCritical()
{
_logActionCritical(_logger, _customData.SomeText, _customData.SomeValue, _customData.SomeDate, _customData, null);
}
// DEFINED ACTION CHECKED LOGGING USAGE
[Benchmark]
public void CheckedActionLoggingTrace()
{
if (_logger.IsEnabled(LogLevel.Trace))
{
_logActionTrace(_logger, _customData.SomeText, _customData.SomeValue, _customData.SomeDate, _customData, null);
}
}
[Benchmark]
public void CheckedActionLoggingCritical()
{
if (_logger.IsEnabled(LogLevel.Critical))
{
_logActionCritical(_logger, _customData.SomeText, _customData.SomeValue, _customData.SomeDate, _customData, null);
}
}
// SOURCE GENERATED LOGGING USAGE
[LoggerMessage(1, LogLevel.Trace, "This is a sample template logging {Text} {Value} {Date} All: @{data}")]
partial void SourcenGenLoggingTrace(string text, int value, DateTime date, CustomData data);
[LoggerMessage(1, LogLevel.Critical, "This is a sample template logging {Text} {Value} {Date} All: @{data}")]
partial void SourcenGenLoggingCritical(string text, int value, DateTime date, CustomData data);
// Benchmark methods
[Benchmark]
public void SourceGenLogTrace()
{
SourcenGenLoggingTrace(_customData.SomeText, _customData.SomeValue, _customData.SomeDate, _customData);
}
[Benchmark]
public void SourceGenLogCritical()
{
SourcenGenLoggingCritical(_customData.SomeText, _customData.SomeValue, _customData.SomeDate, _customData);
}
}
class NullLoggerProvider : ILoggerProvider
{
public ILogger CreateLogger(string categoryName) => new NullLogger();
public void Dispose() { }
class NullLogger : ILogger, IDisposable
{
private int _dummy;
public IDisposable BeginScope<TState>(TState state) => new NullLogger();
public bool IsEnabled(LogLevel logLevel) => logLevel >= LogLevel.Information;
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter) => _dummy++;
public void Dispose() { }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment