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

Reduce boxing in logging #88560

Merged
merged 1 commit into from
Jul 10, 2023
Merged

Reduce boxing in logging #88560

merged 1 commit into from
Jul 10, 2023

Conversation

davidfowl
Copy link
Member

@davidfowl davidfowl commented Jul 9, 2023

  • Logging got overhauled to use CompositeFormat in .NET 8, this allows for non-boxing string formatting via string.Format. There's one piece of code that boxing the generic argument before handing off to string.Format so remove it for primitive types and enums.

Fixes #50768

(while this doesn't fully fix the problem, it's as improved as we would make it for now for < 4 arguments).

PS: Between 4 and 10 arguments, I think we can consider using the new inline array to avoid the object array allocation (probably not worth it, but fun nonetheless).

- Logging got overhauled to use CompositeFormat in .NET 8, this allows for non boxing string formatting via string.Format. There's one piece of code that boxing the generic argument before handing off to string.Format so remove it for primitive types and enums.
@ghost
Copy link

ghost commented Jul 9, 2023

Tagging subscribers to this area: @dotnet/area-extensions-logging
See info in area-owners.md if you want to be subscribed.

Issue Details
  • Logging got overhauled to use CompositeFormat in .NET 8, this allows for non boxing string formatting via string.Format. There's one piece of code that boxing the generic argument before handing off to string.Format so remove it for primitive types and enums.

Fixes #50768

Author: davidfowl
Assignees: -
Labels:

area-Extensions-Logging

Milestone: -

@davidfowl davidfowl requested a review from stephentoub July 9, 2023 23:16
@davidfowl davidfowl changed the title Reduce boxing in logging - Logging got overhauled to use CompositeFormat in .NET 8, this allows for non boxing string formatting via string.Format. There's one piece of code that boxing the generic argument before handing off to string.Format so remove it for primitive types and enums. Reduce boxing in logging Jul 9, 2023
@davidfowl davidfowl requested review from tarekgh and noahfalk July 10, 2023 01:23
@tarekgh tarekgh added this to the 8.0.0 milestone Jul 10, 2023
Copy link
Member

@tarekgh tarekgh left a comment

Choose a reason for hiding this comment

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

LGTM.

@davidfowl davidfowl merged commit ad13e28 into main Jul 10, 2023
@davidfowl davidfowl deleted the davidfowl/fix-boxing branch July 10, 2023 20:50
@davidfowl
Copy link
Member Author

Tks!

Comment on lines +268 to +273
// Avoiding boxing of known types
if (typeof(T).IsPrimitive || typeof(T).IsEnum)
{
stringValue = null;
return false;
}
Copy link
Member

Choose a reason for hiding this comment

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

What benefit does this block of code provide? I'm not seeing where boxing would be coming from without it, at least not in optimized code. For a primitive or an enum, the JIT should effectively get rid of everything else in the method already, since it'll be generically specialized for that value type T and the JIT can tell the value is non-null and not an IEnumerable.

Copy link
Member Author

Choose a reason for hiding this comment

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

at least not in optimized code.

This is what I was worried about. Maybe I was looking at tier 0 code? I can revert, but while profiling this I was seeing boxing and I assumed it was coming from the interface check (if T is IEnumerable).

Copy link
Member

@stephentoub stephentoub Jul 17, 2023

Choose a reason for hiding this comment

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

Maybe I was looking at tier 0 code?

That's my guess.

I assumed it was coming from the interface check (if T is IEnumerable).

That shouldn't box in optimized code (unless the T actually implements IEnumerable, in which case it's not a primitive or an enum, anyway). If it does, we should fix the JIT. @EgorBo?

Copy link
Member

Choose a reason for hiding this comment

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

It looks like both of you're correct - we optimize this in Tier1 but still allocate in Tier0 (although, should not be a real issue for this case because BCL libs are prejitted, hence, the boxing will be always optimized unless user explicitly defines DOTNET_ReadyToRun=0). Filed #88987 with a minimal repro

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah! IIRC allocation profiler sets DOTNET_ReadyToRun=0.

Copy link
Member

Choose a reason for hiding this comment

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

so I can probably remove this workaround in that PR

I think we should remove it, regardless. We generally don't add code to optimize tier 0.

Copy link
Member Author

Choose a reason for hiding this comment

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

Sure I'll send a PR, I just wanted to understand why I was seeing boxing in the tool 😄.

Copy link
Member

Choose a reason for hiding this comment

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

For reference:
image

And:
image

Copy link
Member

@stephentoub stephentoub Jul 17, 2023

Choose a reason for hiding this comment

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

So this doesn't explain why you were seeing boxing from here...

Certainly the boxing via the object argument would result in boxing, and this PR should have fixed that, but I don't know why you would have seen boxing in the tool after your object=>T changes, unless you unchecked that Disable Tiered Compilation setting.

Copy link
Member Author

Choose a reason for hiding this comment

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

@ghost ghost locked as resolved and limited conversation to collaborators Aug 16, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Fix the boxing when using the LoggerMessage.Define is used and values are converted ToString
4 participants