-
Notifications
You must be signed in to change notification settings - Fork 732
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
LogValues structs from LoggerMessage now implement IReadonlyDictionary<string, object> #1849
Conversation
If this PR is considered for merging, I'll provide some tests to cover the implementation. Looking forward to hearing from maintainers, is it something they consider for merging. |
Seems reasonable to me. Thoughts @davidfowl @pakrym @BrennanConroy ? The implementation looks good to me, as you say we'll need tests before merging. They are supposed to behave like dictionaries, so it seems reasonable to implement the interface. |
I'm not sure about the benefits. All consumers would still have to stick to using |
Please find my answers below :-) @pakrym
My motivation is even better performance for
I could add it to the other structure if needed. My aim was to potentially speak up the high-perf scenario. The requirement of implementing of as the if (state is IDictionary<string,object>)
{
var asDict = (IDictionary<string,object>)state;
} as their implementors are aware of https://github.com/dotnet/coreclr/issues/14213 and dotnet/coreclr#14698
My benchmarks show something else, as for cases when one would like to retrieve a value, it's likely that with list it'd be implemented as a LINQ call. I've added the results to the initial description of it. |
I'm actually not too surprised that the |
I'm just providing data @anurse to questions raised above :-) |
Sure it is slightly slower, if not using LINQ it's around ~40% slower:
but no logger ever retrieves a single value, most logger implementations I've seen retrieve all of them or just call the formatter.
Do you know of an existing logger implementation that would benefit from this change? @anurse your call here but I don't think this addition solve an existing problem. |
I see @pakrym . Maybe I should have been clear about the initial motivation of it. So my initial one was code operating on scope and state, checking for loglevel etx in https://github.com/Azure/azure-webjobs-sdk/blob/dev/src/Microsoft.Azure.WebJobs.Logging.ApplicationInsights/ApplicationInsightsLogger.cs but now, when I look through the implementation, it might be not worth it. Especially, as I doesn't use statements prepared with Being given that the initial author of this PR is unsure whether it's worth it 😛 I can close this PR. |
I guess I'm curious why the category name and log level are in the scope in your example instead of just using the values associated with the log message itself. Plus, you're already merging the scope data into a dictionary (as far as I can tell) so I'm not sure what the benefit is here. Like I said, it doesn't seem problematic at all, but I do agree with @pakrym that in general a logger wants all the scope data, so the gain from using Seems like maybe closing is what we're converging on here. |
This PR introduces an additional interface implementation for structs used for high-performance logging. The additional interface is
IReadonlyDictionary<string, object>
which should allow slightly faster querying of the state/scope object byILogger
implementations, especially taking into consideration thatLog<TState>
is a generic method, and there's some awesome work related to deviritualizing calls to structs implementing interfaces.Usages
With a change like this, there's potential to replace some allocations in various libraries, without creating specific types (they can be inferred from the parsed format & values) and replacing the allocated dictionaries. For example:
Benchmarks
To benchmark potential gains I used the following benchmark, trying to compare finding a value via LINQ over
IReadOnlyList
and a direct access to a dictionary API. Maybe there's a better way, but my assumption is that this is the way one would access it in the implementation.