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

Performance measurements #3490

Closed
imanushin opened this issue Jun 18, 2019 · 15 comments
Closed

Performance measurements #3490

imanushin opened this issue Jun 18, 2019 · 15 comments

Comments

@imanushin
Copy link
Contributor

Hi Team!

I wrote short article regarding NLog (and log4net) performance (with benchmark comparison, etc.).

What do you think, is it reasonable to add article link into the NLog documentation?

Target text: https://medium.com/@imanushin/net-logging-performance-comparison-20c83aa84333

@304NotModified
Copy link
Member

Hi!

Yes I think that's a good idea, bit more sure where exactly.

PS: please be sure to use the lastest NLog version (can't find the versions for now in your article, on mobile), and please add them to the article :). Almost every NLog version has a performance improvement 😄

PS 2. Benchmark with Serilog would also be nice ;)
This is done in the past although many benchmarks won't use equal configs between libraries (and so big unfair difference). If you have any questions about performance for your article, please let us know!

@snakefoot
Copy link
Contributor

@imanushin Cases with KeepFileOpen=true mean that for each logging event NLog opens file (e.g. creates file system handle), then it writes data to disk

Sounds like you mean KeepFileOpen=false

@snakefoot
Copy link
Contributor

snakefoot commented Jun 18, 2019

@imanushin As you can see, wrapper configuration allows logger to keep a lot of logging lines in the memory.

Instead of configuring BatchSize = 4096 and FullBatchSizeWriteLimit = 128, then I guess you are looking for for queueLimit=10000 (Controls how much memory it uses)

BatchSize = 4096 means it will write in batches for 4096 LogEvents at a time (performs batch-dequeue and then batch-write). Writing in very large batches actually hurts performances. On my SSD then the "sweet spot" is BatchSize=500 for file-target. (Default is 200 which work well for Nlog-targets that uses network)

FullBatchSizeWriteLimit = 128 means it will perform a single "throttle" (Default 1 ms) after having written 128 full batches of BatchSize = 4096 without internal queue becoming empty (Default is 5 which work well for NLog-targets that uses network).

@snakefoot
Copy link
Contributor

snakefoot commented Jun 18, 2019

@imanushin Logger construction Results.

The test-case for CreateNLogTypeOfLogger does not compare to CreateLog4NetLogger

  • CreateNLogTypeOfLogger - Captures current callstack and extracts LoggerName and then create a logger of the type provided. If the type provided does not inherit from NLog Logger-object then it logs error and fallback to creating a standard NLog Logger.
  • CreateLog4NetLogger - FullName is extracted from Type provided, and then create a logger with that name.

The valid NLog test should be this (Instead of being a bad version of CreateNLogDynamicLogger-test)

[Benchmark]
public object CreateNLogTypeOfLogger()
{
    return new[]
    {
        NLog.LogManager.GetLogger(typeof(BaseTest).FullName), // x16 times
    };
} 

And why the extra creation of array ? (Think return new[] should be removed from all 3 benchmark tests).

@snakefoot
Copy link
Contributor

snakefoot commented Jun 18, 2019

@imanushin Regarding benchmarks then there is huge difference between:

  • net472 - 32 bit
  • net472 - 64 bit (64 bit compiler produces more optimized code)
  • netcore21 (netcore-runtime is faster).

There is also a huge difference between using GcServer or not. See my own tests here

@snakefoot
Copy link
Contributor

snakefoot commented Jun 18, 2019

@imanushin ConcurrentWrites option orders system to gain and release Mutex,

NLog with net472 running on Windows will actually perform "atomic" writes without using Mutex. Instead it will use FileSystemRights.AppendData | FileSystemRights.Synchronize. It provides atomic file-writes across processes. It is similar to log4net.Appender.FileAppender+MinimalLock.

NLog will use Mutex on non-Windows platforms when available, else it will fallback to opening/closing the file on each write.

You can add the file-target parameter ForceMutexConcurrentWrites=true and it will change from using "atomic"-writes into actually using "mutex"-writes (Used by default on NetCore)

@imanushin
Copy link
Contributor Author

imanushin commented Jun 19, 2019

@snakefoot , @304NotModified ,

Thank you for feedback! I fixed typo with KeepFileOpen=true.

I used NLog version 2.6.3 (please see project here). I added them to article.

Regarding to Create*Logger - unfortunately, these tests are not fully correct (as I noticed in article, will highlight this again a bit later). The main reason: I could not do honest black-box checking of this method, because looks like both libraries store something in the internal dictionaries. So many calls are followed with Out Of Memory error. I just tried to show, that difference between new logger creation and single line writing is not dramatic. Also x16 times and array creation were added just to have ability to run all benchmark from the single suite.

I agree with queue limit and batch sizes, I'll re-run tests with that parameters.

I used Win x64, because it is faster version of executable, which can have both libraries in the single memory. This is honest (from my point of view), because the same application operates with the both libraries. I think I'll prepare NLog vs SeriLog comparison with also .Net Core/.Net Framework differences.

And I'll fix article part, which describes Mutex operations.

Also: I wrote Russian-language article too (just translation), I update it with small delay.

@imanushin imanushin changed the title [Question] Performance measurements Performance measurements Jun 19, 2019
@snakefoot
Copy link
Contributor

I used NLog version 2.6.3

I guess you mean NLog version 4.6.3 :)

@imanushin
Copy link
Contributor Author

@snakefoot , yes, you are right.

@imanushin
Copy link
Contributor Author

Added page: https://github.com/NLog/NLog/wiki/External-articles
And added page mention in the end of the FAQ: https://github.com/NLog/NLog/wiki/faq

Could you please review there (and please rollback if I'm doing wrong)?

@snakefoot
Copy link
Contributor

snakefoot commented Jul 29, 2019 via email

@imanushin
Copy link
Contributor Author

@snakefoot, done: I removed the new page, rolled back FAQ and updated the Web-resources.

@304NotModified
Copy link
Member

OK thanks, I assume this could be closed now :)

@snakefoot
Copy link
Contributor

@imanushin Could still be nice if you could fix this part of the article code:

[Benchmark]
public object CreateLog4NetLogger()
{
    return new []
    {
        LogManager.GetLogger(typeof(BaseTest)), // x16 times
    };
}

[Benchmark]
public object CreateNLogTypeOfLogger()
{
    return new[]
    {
        NLog.LogManager.GetCurrentClassLogger(typeof(BaseTest)), // x16 times
    };
}

[Benchmark]
public object CreateNLogDynamicLogger()
{
    return new[]
    {
        NLog.LogManager.GetCurrentClassLogger(), // x16 times
    };
}

Removing the return new[], then you could get rid of the problem with:

I failed to create reproducible benchmark which does not lead to an “Out Of Memory” issue

@imanushin
Copy link
Contributor Author

@snakefoot , yes, will remove and return to the thread.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants