Skip to content
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

Avoid string/StringBuilder/char[] allocation in LogValuesFormatter's ctor #44746

Merged
merged 1 commit into from
Nov 17, 2020

Conversation

stephentoub
Copy link
Member

This is producing thousands of allocations at ASP.NET startup, due to almost 1000 call sites to LoggerMessage.Define.

Related to #44598

cc: @eerhardt, @maryamariyan

…ctor

This is producing thousands of allocations at ASP.NET startup, due to almost 1000 call sites to LoggerMessage.Define.
@stephentoub stephentoub added this to the 6.0.0 milestone Nov 16, 2020
@ghost
Copy link

ghost commented Nov 16, 2020

Tagging subscribers to this area: @maryamariyan
See info in area-owners.md if you want to be subscribed.

Issue Details
Description:

This is producing thousands of allocations at ASP.NET startup, due to almost 1000 call sites to LoggerMessage.Define.

Related to #44598

cc: @eerhardt, @maryamariyan

Author: stephentoub
Assignees: -
Labels:

area-Extensions-Logging, tenet-performance

Milestone: [object Object]

sb.Append(format, scanIndex, openBraceIndex - scanIndex + 1);
sb.Append(_valueNames.Count.ToString(CultureInfo.InvariantCulture));
vsb.Append(format.AsSpan(scanIndex, openBraceIndex - scanIndex + 1));
vsb.Append(_valueNames.Count.ToString());
_valueNames.Add(format.Substring(openBraceIndex + 1, formatDelimiterIndex - openBraceIndex - 1));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be worth delaying this Substring alloc?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delaying it to when?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delaying it until the string is actually used.

https://source.dot.net/#Microsoft.Extensions.Logging.Abstractions/LogValuesFormatter.cs,a31f3c3b2cea5615,references

I am not super familiar with this area, but if we only captured the Ranges here, and returned the _valueNames as ReadOnlyMemory<char>, maybe we could save alloc'ing these as strings all together?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe we could save alloc'ing these as strings all together?

If this is likely, then yeah, we should consider that. But I have no idea how common that is (and if it's at all common, it'll end up being worse as we'll end up having stored the ranges and then needing to also store / replace that with the constructed strings).

@davidfowl?

Let's address it separately.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would stringy those up front.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Meaning as-is, right? Does that mean these names are generally used?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep. We have another source generator thing that will replace this.

Copy link
Member

@eerhardt eerhardt Nov 18, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was roughly what I was thinking: eerhardt@aa33457. At first I thought I could eliminate the substring allocs all together.

However, it appears that there is a hidden expectation that the scope objects implement IReadOnlyList<KeyValuePair<string, object>>, which means this would be a breaking change. Or we could make the LogValues structs implement both IReadOnlyList<KeyValuePair<string, object>> and IReadOnlyList<KeyValuePair<ReadOnlyMemory<char>, object>>, and have the Console logger (and any other loggers) check for both.

Copy link
Member

@eerhardt eerhardt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. Just had a simple question.

@stephentoub stephentoub merged commit 69d6127 into dotnet:master Nov 17, 2020
@stephentoub stephentoub deleted the loggeralloc branch November 17, 2020 10:33
@ghost ghost locked as resolved and limited conversation to collaborators Dec 18, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants