-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
FileTarget - Faster async processing of LogEvents for the same file #1683
FileTarget - Faster async processing of LogEvents for the same file #1683
Conversation
Cool! Could you send a test program for this to https://github.com/NLog/NLog-Performance-tests ? |
@@ -61,14 +62,14 @@ internal static class SortHelpers | |||
/// <returns> | |||
/// Dictionary where keys are unique input keys, and values are lists of <see cref="AsyncLogEventInfo"/>. | |||
/// </returns> | |||
public static Dictionary<TKey, List<TValue>> BucketSort<TValue, TKey>(this IEnumerable<TValue> inputs, KeySelector<TValue, TKey> keySelector) | |||
public static IDictionary<TKey, IList<TValue>> BucketSort<TValue, TKey>(this IEnumerable<TValue> inputs, KeySelector<TValue, TKey> keySelector) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIK the usage of interfaces is always slower than the direct type. Not sure if this is also for these cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any idea about this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes the IList prevents us from using the List-struct-enumerator. This is also why I have changed the iteration of a single bucket into a for-loop.
Current coverage is 80% (diff: 84%)
|
When using the following setup with Tester1, then the new BucketSort gives 1.200.000 msg/sec (Before 1.000.000 msgs/sec). Together with less garbage allocation.
|
That would be an very nice improvement! |
This also counts for the aysnc usage, isn't it? |
Reviewed 7 of 11 files at r1, 2 of 2 files at r2, 2 of 2 files at r3. Comments from Reviewable |
will try to test this, this week |
Yes it will also improve the async-wrapper-performance. But because of the timer-throttle, then it is difficult to see this improvement (Requires very big batch-sizes). But together with #1669 (with sleeptime=0) then it should give a significant performance boost. |
Luckily #1669 has been merged :) |
Just merged with master to try the async-wrapper. This PR now improves from 950.000 msgs/sec to 1.050.000 msgs/sec.
When using timeToSleepBetweenBatches="1" then this PR improves performance from 800.000 msgs/sec. to 850.000 msgs/sec. |
…by skipping dictionary allocation and insert
af8d297
to
13afa97
Compare
I have tested this case with master (639b40f) and pr/1683 (49d3e3d) and don't see any performance difference. Both will get around 240-260K/s. Any idea why?
Release build, https://github.com/NLog/NLog-Performance-tests/tree/7d3bbe83db1c42195c78cb313203b8f792e6019d update: |
I have modified the Tester1 program to just do logger.Debug("Line : 99999999"); , instead of adding extra allocations to the test. I performed a test with the above async-wrapper config, and it improved from 1.000.000 msgs/sec to 1.100.000 msg/sec. When using the buffer-wrapper-config then it improved from 1.000.000 msgs/sec to 1.200.000 msgs/sec. If I add {threadname} into the layout (so the Logger-thread performs the rendering), then the buffer-wrapper improves from 900.000 msgs/sec to 1.000.000 msgs/sec. When comparing in the profiler then the old BucketSort takes 3% of the total time, where the new takes 0.5% of the total time. |
So there is only a difference when using fixed values? Which is a valid case, as long as the non-fixed values (the one I have tested), won't suffer - (and that is not the case, no performance impact, also not lower) |
There is also an improvement when adding {threadname} to the layout, so not just fixed values (See previous comment) |
8ec38dd
to
d5886b1
Compare
d5886b1
to
8c4b283
Compare
Removed code regarding ArraySegment, as this logic is for another PR |
Reviewed 11 of 11 files at r5. src/NLog/Internal/SortHelpers.cs, line 95 at r5 (raw file):
Are you sure this code is used? I only see it in the tests? (reviewing in the webinterface) src/NLog/Targets/FileTarget.cs, line 1019 at r5 (raw file):
why ++i and not i++? Comments from Reviewable |
src/NLog/Internal/SortHelpers.cs, line 95 at r5 (raw file):
|
src/NLog/Targets/FileTarget.cs, line 1019 at r5 (raw file):
|
Review status: all files reviewed at latest revision, 2 unresolved discussions. src/NLog/Internal/SortHelpers.cs, line 95 at r5 (raw file):
|
src/NLog/Targets/FileTarget.cs, line 1019 at r5 (raw file):
|
Review status: all files reviewed at latest revision, 1 unresolved discussion. src/NLog/Targets/FileTarget.cs, line 1019 at r5 (raw file):
|
8c4b283
to
68e684e
Compare
src/NLog/Targets/FileTarget.cs, line 1019 at r5 (raw file):
|
4fdd7e1
to
8d01583
Compare
…by skipping dictionary allocation and insert (cleanup)
8d01583
to
c5c6425
Compare
Reviewed 3 of 3 files at r6. Comments from Reviewable |
When performing async batch writing, then LogEvents destination (file or database) can be decided by a Layout.
The default situation is that all LogEvents should go to the same destination. Have changed BucketSort() to optimize for this case.
This skips allocation of Dictionary and inserting all LogEvents into a new List of this dictionary
This change is