Skip to content
This repository was archived by the owner on Dec 13, 2018. It is now read-only.

LoggerExtensions performance concerns #523

Closed
strohhut opened this issue Nov 19, 2016 · 15 comments
Closed

LoggerExtensions performance concerns #523

strohhut opened this issue Nov 19, 2016 · 15 comments
Assignees
Milestone

Comments

@strohhut
Copy link

Say the log level is warning and I have the following in my code:

_logger.LogInformation("Id is {Id}", myIntId);

This creates a params array and a FormattedLogValues and boxing from int to object will occur although nothing will be logged.

Wouldn't it make more sense to provide some overloads for typical amounts of arguments like

public static void LogInformation<T1, T2>(this ILogger logger, string message, T1 arg1, T2 arg2)
{
    if (logger.IsEnabled(LogLevel.Information))
    {
        logger.Log(LogLevel.Information, 0, new FormattedLogValues(message, new object[] { arg1, arg2 }), null, _messageFormatter);
    }
}
@benaadams
Copy link
Contributor

The zero allocation pattern is demonstrated in KestrelTrace.cs

@strohhut
Copy link
Author

OK, so there are two extremes. Many allocations with LoggerExtensions (what most people will use) or minimal allocations with LoggerMessage.Define (which seems a bit hidden and the class name LoggerMessage is a bit strange for a delegate factory) that basically requires you to create and store a delegate where you would normally reuse a logger.

What about some faster ILogger extensions?

@roji
Copy link
Member

roji commented Dec 13, 2016

+1 on this.

@MichaCo
Copy link

MichaCo commented Dec 13, 2016

@benaadams @strohhut I actually didn't know about the LoggerMessage factory before Ben mentioned it here ~~
I tried that in some tests we are doing currently with per request logging and it was a ~20% performance increase when just logging into the void. Interesting... I agree that the logging framework should either promote that option more and make it more first class, or just do some more fancy things internally to improve the performance per default.

@muratg
Copy link

muratg commented Jan 17, 2017

Assigning to @BrennanConroy for investigation.

cc @mikeharder

@BrennanConroy
Copy link
Member

You can also easily avoid unneeded allocations by using

if (logger.IsEnabled(LogLevel.Information))
{
    logger.LogInformation(...);
}

@strohhut
Copy link
Author

strohhut commented Jan 20, 2017

Yeah, that's obvious. But who wants to do that (four to five lines for every logging statement, remember a closing brace should be followed by a blank line under most circumstances)?

@davidfowl
Copy link
Member

People that want to avoid a performance hit. We do it all over the framework. We also use LoggerMessage. These are all valid options we should document.

What does the "what about some faster ILoggerExtensions" suggestion? Is that something concrete? Do you have ideas ok how to make it better?

@roji
Copy link
Member

roji commented Jan 20, 2017

@davidfowl see the original post, simply providing some generic overloads to prevent the allocation of the params array in most cases would help - it's standard practice in both logging packages and other APIs...

@davidfowl
Copy link
Member

Let me dig up the PR where we decided against this change before. Making the extension methods check is enabled by default makes the peformancd worse when the caller checks as well. That was part of the original push back against doing so.

@roji
Copy link
Member

roji commented Jan 20, 2017

Note that there are two separate proposals in the original post:

  • Add generic overloads to prevent the params array allocation
  • Perform an "is enabled" check immediately inside the method

The two are definitely unrelated, I personally feel the first is much more needed than the second.

@strohhut
Copy link
Author

@davidfowl You are saying that checking IsEnabled is slower than those allocations?

But checking IsEnabled happens in the delegates created by LoggerMessage.Define. And LoggerMessage.Define is used for performance reasons as far as I understand.

@davidfowl
Copy link
Member

Add generic overloads to prevent the params array allocation

Performance numbers would definitely help this discussion.

Here's the old PR:

#101

But checking IsEnabled happens in the delegates created by LoggerMessage.Define. And LoggerMessage.Define is used for performance reasons as far as I understand.

The problem with the extension methods that check for you is that ends up being the default. If you want to check IsEnabled yourself, you end up paying that IsEnabled cost twice (then you end up having to go out of your way to find the extension method without the IsEnabled check)

@glennc glennc added this to the Discussions milestone Feb 22, 2017
@glennc
Copy link
Member

glennc commented Feb 22, 2017

We have a bug on docs to increase our documentation of the other logging patterns: dotnet/AspNetCore.Docs#2810

Moving this to the discussion milestone until something we want to actually implement falls out of it.

@muratg
Copy link

muratg commented May 12, 2017

We are closing this issue because no further action is planned for this issue. If you still have any issues or questions, please log a new issue with any additional details that you have.

@muratg muratg closed this as completed May 12, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants