-
Notifications
You must be signed in to change notification settings - Fork 831
Output and rendering improvements #977
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
Conversation
Oh, and I'll fix the tests ;-) |
Now includes #958, #956 and the optional JSON output style suggested in serilog/serilog-sinks-console#7. This is, unfortunately, a bit of a monster changeset. Digging in to output formatting unearthed a lot of code that needed cleanup - I ended up fixing a few things like unused Here are the main points:
Now to bench... :-) |
Having trouble with the benchmark runner, will need to come back to this when it's sorted out :-( |
// This could be lazier: the output properties include | ||
// everything from the log event, but often we won't need any more than | ||
// just the standard timestamp/message etc. | ||
var outputProperties = OutputProperties.GetOutputProperties(logEvent, _outputTemplate); |
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.
The changes in this method are the meat of the "less allocations" change - GetOutputProperties()
above would previously allocate objects for {Level}
, {Message}
, {Exception}
etc. Instead now we just iterate and examine property names, and write the output inline.
|
||
namespace Serilog.Rendering | ||
{ | ||
static class MessageTemplateRenderer |
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 class is the remainder - formatting of message templates is externalized from the MessageTemplate
and related token classes here.
I expect there will be a small perf hit because dispatch is done by switching on type, rather than by virtual dispatch.
After a quick look, it seems that a few class namespaces have changed. Is this considered a breaking change? |
Thanks for checking it out, @johnduhart. It would be if the namespaces contained public types, but these are all internal types so there shouldn't be externally visible effects this time around. ...unless I've overlooked something public in there, of course :-) |
Oh, right, I guess I overlooked that 😅 |
I am really itching to clean up some of the public type names and namespaces - they've been frozen for compatibility reasons for three years or so now, and a few like #839 would be worthwhile improvements. Someday! |
@nblumhardt can you link to your Resharper profile/settings? Just want to be on the same page. |
@merbla I just exported them in their entirety and included the dotsettings file in this PR: https://github.com/serilog/serilog/pull/977/files#diff-a08cec6edf37e99e02d322888266d97d :-) |
@nblumhardt a bit of love is needed post #976 |
OutputTemplateRenderingBenchmarkBefore:
After:
This doesn't take the garbage reduction into account, so I think it's nice to get a ~40% perf boost along the way. MessageTemplateRenderingBenchmarkBefore:
After:
So, the switch from virtual to type-driven dispatch looks like it will cost about 10%. Not awesome, but also not too worrying. The broken benchmark turned up some problems with this one in general, namely, the code intended to reset the output |
Fixed the message template rendering benchmark; this is the "after":
Knocks ~25% off the overall time, meaning the differences in the earlier run are probably understated by about that much. BDN 0.10.6 doesn't get the .NET Framework target running successfully either, unfortunately. |
} | ||
else | ||
{ | ||
output.Write(new string(' ', pad)); |
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.
We now only allocate if the padding applied to a token is > 80 chars. (We allocated for every render, previously.)
I think this'd benefit from a look over, now. Might be some future improvements to make, but I'm happy that it makes enough progress to be a worthwhile merge. |
… on select benchmarks.
Ran these again, with the benchmark changes backported to my local BenchmarkDotNet=v0.10.6, OS=Windows 10 Redstone 2 (10.0.15063)
Processor=Intel Core i7-7700HQ CPU 2.80GHz (Kaby Lake), ProcessorCount=8
Frequency=2742186 Hz, Resolution=364.6726 ns, Timer=TSC
dotnet cli version=1.0.4
[Host] : .NET Core 4.6.25211.01, 64bit RyuJIT
DefaultJob : .NET Core 4.6.25211.01, 64bit RyuJIT OutputTemplateRenderingBenchmarkBefore:
After:
MessageTemplateRenderingBenchmarkBefore:
After:
I'm not unhappy with these, but I don't think |
Alright, figured out the regression :-) This is the "after" now:
The additional cost was a couple of argument checks. The numbers are so small I think it probably makes sense to leave (at least some of) the extra checks in. I'll see what I can come up with. |
Ready to go. There's one further sneaky change here - the classes |
Is there a chance anyone has some time to look over this one? :-) |
@@ -62,7 +65,7 @@ public static class OutputProperties | |||
/// </summary> | |||
/// <param name="logEvent">The log event.</param> | |||
/// <returns>A dictionary with properties representing the log event.</returns> | |||
[Obsolete("Pass the full output template using the other overload.")] | |||
[Obsolete("These implementation details of output formatting will not be exposed in a future version.")] | |||
public static IReadOnlyDictionary<string, LogEventPropertyValue> GetOutputProperties(LogEvent logEvent) |
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.
Just confirming this is the main consumer we are worried about? https://github.com/serilog/serilog-sinks-literate/blob/dev/src/Serilog.Sinks.Literate/Sinks/Literate/LiterateConsoleSink.cs#L88
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.
That's the one 👍
@@ -74,7 +77,7 @@ public static class OutputProperties | |||
/// <param name="logEvent">The log event.</param> | |||
/// <param name="outputTemplate">The output template.</param> | |||
/// <returns>A dictionary with properties representing the log event.</returns> | |||
public static IReadOnlyDictionary<string, LogEventPropertyValue> GetOutputProperties(LogEvent logEvent, MessageTemplate outputTemplate) | |||
internal static IReadOnlyDictionary<string, LogEventPropertyValue> GetOutputProperties(LogEvent logEvent, MessageTemplate outputTemplate) |
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.
Do we call this out as a breaking change in 2.5?
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 it would make sense to list it prominently. Super surprised if it breaks anything out there today, though.
@@ -18,6 +18,8 @@ | |||
<GenerateAssemblyVersionAttribute>false</GenerateAssemblyVersionAttribute> | |||
<!-- Don't reference the full NETStandard.Library --> | |||
<DisableImplicitFrameworkReferences>true</DisableImplicitFrameworkReferences> | |||
<TreatWarningsAsErrors>True</TreatWarningsAsErrors> |
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.
GOLD 🥇
|
||
namespace Serilog.Parsing | ||
{ | ||
/// <summary> | ||
/// A message template token representing literal text. | ||
/// </summary> | ||
public class TextToken : MessageTemplateToken | ||
public sealed class TextToken : MessageTemplateToken |
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.
Another note for 2.5 release.
@nblumhardt all good from me, just some questions to make sure these changes are noted in release. |
Lets get this to |
Thanks for the review @merbla 👍 |
Bundling a whole range of output and template rendering improvements for #958 here.
We won't be able to remove all of the obsolete code until the literate console sink has been weaned off of
OutputProperties.GetOutputProperties()
, but when that's done we should be able to clear out a lot of gunk here.Currently just making the first few moves, will streamline things a bit before this is "done".