-
Notifications
You must be signed in to change notification settings - Fork 103
Description
[LoggerMessage] generate a struct state, in an attempt to reduce allocations.
For this to be meaningful, state should not be boxed, but it is in AsLoggableValue:
// Current version:
static object? AsLoggableValue<TState>(TState state, Func<TState, Exception?, string>? formatter)
{
object? stateObj = state; // <- always boxing!!
if (formatter != null)
stateObj = formatter(state, null);
return stateObj;
}
// Suggested:
static object? AsLoggableValue<TState>(TState state, Func<TState, Exception?, string>? formatter)
{
object? stateObj = null;
if (formatter != null)
stateObj = formatter(state, null);
return stateObj ?? state; // <- boxed only when needed
}Note that in the case of [LoggerMessage] a formatter is always provided (to create the formatted string without boxing of its parameters), so stateObj will never be null and state will not be boxed.
For the curious mind, in PrepareWrite() the code if (state is IEnumerable<..> structure) does not result in boxing because JIT compiles each struct TState separately and statically optimizes these conditions and interfaces, as can be seen in this disassembly (call S.GetEnumerator):
https://sharplab.io/#v2:EYLgtghglgdgNAFxBAzmAPgAQEwEYCwAUJgAwAEmuAdAMID2ANgwKYDGCUdMKA3EaRVwAWPoSIoEAJwCu7MgGUyIQQGYAPAGlmATwBqEBtOYAFaJLWUScMnWAArNggB8TogG8iZLxRVkAkgCiMNJgzJIQCHTmWnoGRqZQ5pbWtg7sLmQA4swIQSFhEVEAFACUnt4ehN7VZAgAFpJ0AO5kMMwtAHJ0CH5gAA4soTAIzAAmAQAerMx9HFylotUAvkTlXoHBoeGRkqpU2bmbBTula2SVNd71jS1tnd29A8xDI+NTM3MwC2crhL/8vhwZBo5zOAG15HUIJI+gAZCDAKgAJWkwygoSoACkoAhsm1JFBWEUENo+sw6AAzIryEolAC6Z0wgNwADYKEIyABZNQAFScRR5ZAmJVBVRqUApZCKEzIUBQqk0On0hhMZgsuCsNnsjgyzDKYuqF0u3gpUWYEFYdSlADdoWQANbWvqymBkPVnS5G401SgATiKjr6VBiJUW3rIv0uke8vyWQA==