-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
LoggerMessage formatter performance improvements #58524
Conversation
Tagging subscribers to this area: @maryamariyan Issue DetailsRemark: This is still a draft, but before I spend a lot of time, I'd appreciate a soft yay or nay from people responsible for the logging area. It will take more time and it'd be great if I could get some initial feedback. This PR is a result of profiling/benchmarking a piece of code that touched Durable Functions and used ApplicationInsights. I found that the logger that is provided as the official package calls The idea behind this PR would be to improve the BenchmarksInitial benchmarks, even with some functionality missing, looks extremely promising. Both the time and the allocations (no boxing!) are reduced BenchmarkDotNet=v0.13.1, OS=Windows 10.0.19042.1165 (20H2/October2020Update)
Intel Core i7-6700HQ CPU 2.60GHz (Skylake), 1 CPU, 8 logical and 4 physical cores
.NET SDK=6.0.100-preview.7.21379.14
[Host] : .NET 6.0.0 (6.0.21.37719), X64 RyuJIT
DefaultJob : .NET 6.0.0 (6.0.21.37719), X64 RyuJIT
|
@maryamariyan Thank you for chiming in. Looking forward for your opinion on whether this is something we want to pursue. This will require a lot of polishing, but the initial idea is in there. If you need any more input, ping me. I'm looking forward to hearing your opinion. |
Any thoughts/opinions @maryamariyan ? |
Could I get an update on this or ETA where I can expect some input whether to push forward with this? |
It's been 20 days since a request to get some input. Could sb chime in and let me know whether this is something that has a possibility to be merged in? I don't want to propose sth to get it rejected. |
It should not take this long. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is an interesting idea. It may make sense pursue this more. It would be good to get the CI passing so we know that the change doesn't affect behavior.
Thoughts @davidfowl @pakrym ?
@@ -540,8 +585,24 @@ public LogValues(LogValuesFormatter formatter, T0 value0) | |||
} | |||
} | |||
|
|||
public override string ToString() | |||
{ | |||
Span<char> output = stackalloc char[1024]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do we know 1024
is big enough?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should use ValueStringBuilder
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not. This was just to please some initial tests and I'll need to amend it in a much smarter way 😄
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
private static int Append<TValue>(Span<char> span, TValue value, string format) | ||
{ | ||
// ReSharper disable once MergeCastWithTypeCheck |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What are these comments for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pleasing Resharper
. Will remove.
private static int Append<TValue>(Span<char> span, TValue value, string format) | ||
{ | ||
// ReSharper disable once MergeCastWithTypeCheck | ||
if (value is ISpanFormattable) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (value is ISpanFormattable) | |
if (value is ISpanFormattable spanFormattable) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe I was falling with having it JITted without boxing. It was a while ago. Will take a look at it and use the new syntax if possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, today the JIT can't avoid boxing when using if (value is ISpanFormattable sf) { sf.TryFormat(...); }
but it can when doing if (value is ISpanFormattable) { ((ISpanFormattable)value).TryFormat(...); }
; the latter case is easier to prove correct.
Thx for chiming in @eerhardt . If this is looks like an initially interesting idea let me give it a spin and make CI green. Also, if there are some more opinions about it, let me know. |
In #50330 we discussed using the proposed CompositeFormat as an implementation detail under LoggerMessage.Define. Is this essentially doing the same thing? |
I wasn't aware of this beautiful proposal @stephentoub ! Actually, the case that I'm raising here, is mentioned in the original repo https://github.com/geeknoid/FastFormatting#template-based-format-strings ! Having this said, I'm closing this PR as the mentioned functionality is set to Future milestone. Logging will get this lunch for free 😅 |
Remark: This is still a draft, but before I spend a lot of time, I'd appreciate a soft yay or nay from people responsible for the logging area. It will take more time and it'd be great if I could get some initial feedback. The initials numbers are amazing, and being given that this PR targets
LoggerMessage
, which should be high-perf, this looks like a potential huge gain for all the loggers calling the formatter.This PR is a result of profiling/benchmarking a piece of code that touched
Durable Functions
and usedApplicationInsight
. I found that the logger, that is provided as the official package, callsformatter
, having the state not only logged as usual key-value pairs but also as a formatted string.https://github.com/microsoft/ApplicationInsights-dotnet/blob/d54bae8aeaf74b6fa08c8033c2ce54ea6d8f437b/LOGGING/src/ILogger/ApplicationInsightsLogger.cs#L113
https://github.com/microsoft/ApplicationInsights-dotnet/blob/d54bae8aeaf74b6fa08c8033c2ce54ea6d8f437b/LOGGING/src/ILogger/ApplicationInsightsLogger.cs#L94
The idea behind this PR would be to improve the
formatter
built byLoggerMessage
by capturing much more context during the build up ofLogValuesFormatter
and to use it when formatting the value. I'm aware that LogValues should be kept small (big structs are no-no for perf) and this can be amended later on by capturing the formatting info into a separate object.Benchmarks
Initial benchmarks, even with some functionality missing, looks extremely promising. Both the time and the allocations (no boxing!) are reduced