Skip to content

Logging methods created by generators allocate if LogLevel is passed #61162

Closed
@shadow-cs

Description

@shadow-cs

Description

The new Logging generators for LoggerMessage cause the generated implementations to allocate due to usage of a method group which the generator assigns to Func<TState, Exception?, string> formatter in a ILogger.Log call. This is due to a fact that method groups are not cached whereas lambdas are (which is not always obvious, see dotnet/roslyn#5835).

Configuration

  • 10.0.19043.1319 (21H1/May2021Update)
  • .NET 6.0.0 (6.0.21.48005), X64 RyuJIT
  • Intel Core i7-4770S CPU 3.10GHz (Haswell)

Data

Method Mean Error StdDev Ratio RatioSD Gen 0 Allocated
NoLevel 21.37 ns 0.454 ns 0.558 ns 1.00 0.00 - -
WithLevel 20.95 ns 0.431 ns 0.443 ns 0.98 0.04 0.0153 64 B
FixedWithLevel 13.94 ns 0.260 ns 0.231 ns 0.65 0.03 - -

Fix suggestion

Instead of generating a Format method like this:

public static string Format(__StateStruct state, global::System.Exception? ex) => state.ToString();

Generate it like this:

public static readonly Func<__StateStruct, global::System.Exception?, string> Format = (state, ex) => state.ToString();

But generally speaking, fixing the compiler and/or the runtime would be a better way everybody can benefit from 😉.

Note

As can be seen from the benchmarks below, generated calls without LogLevel can be further improved by using a similar structure as with the state as calls with LogLevel are using to achieve better performance.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions