Skip to content

use ArrayPool instead of having a private buffer cache - #45690

Merged
adamsitnik merged 18 commits into
dotnet:mainfrom
adamsitnik:NtProcessInfoHelperRemoveCache
Aug 19, 2021
Merged

use ArrayPool instead of having a private buffer cache#45690
adamsitnik merged 18 commits into
dotnet:mainfrom
adamsitnik:NtProcessInfoHelperRemoveCache

Conversation

@adamsitnik

@adamsitnikadamsitnik commented Dec 7, 2020

Copy link
Copy Markdown
Member

Contributes to #45315

usingSystem.Threading.Tasks;usingMicrosoft.AspNetCore.Builder;usingMicrosoft.AspNetCore.Hosting;usingMicrosoft.Extensions.Configuration;namespaceTemplate{publicclassStartup{publicStartup(IConfigurationconfiguration)=>Configuration=configuration;publicIConfigurationConfiguration{get;}// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.publicvoidConfigure(IApplicationBuilderapp,IWebHostEnvironmentenv){app.UseRouting();app.UseEndpoints(routeBuilder =>{routeBuilder.Map("GetProcesses", context =>{foreach(varprocessinSystem.Diagnostics.Process.GetProcesses()){process.Dispose();}returnTask.CompletedTask;});});}}}

Citrine (28 cores):

loadbeforeafter
CPU Usage (%)34
Cores usage (%)85102
Working Set (MB)4848
Build Time (ms)5,0574,123
Start Time (ms)00
Published Size (KB)76,40176,401
.NET Core SDK Version3.1.4043.1.404
First Request (ms)101106
Requests/sec14,39216,706
Requests216,986251,968
Mean latency (ms)35.5330.61
Max latency (ms)301.49310.73
Bad responses00
Socket errors00
Read throughput (MB/s)1.261.47
Latency 50th (ms)31.9429.67
Latency 75th (ms)40.0531.19
Latency 90th (ms)49.3136.68
Latency 99th (ms)69.8348.34

Perf (12 cores):

loadbeforeafter
CPU Usage (%)1012
Cores usage (%)118142
Working Set (MB)4949
Build Time (ms)5,8775,898
Start Time (ms)00
Published Size (KB)76,40176,401
First Request (ms)103106
Requests/sec13,49917,852
Requests203,683269,349
Mean latency (ms)38.0628.65
Max latency (ms)240.17168.62
Bad responses00
Socket errors00
Read throughput (MB/s)1.181.57
Latency 50th (ms)38.5726.50
Latency 75th (ms)46.4436.76
Latency 90th (ms)57.8040.75
Latency 99th (ms)84.3457.51

No difference for micro-benchmarks (this was expected):

| Method Toolchain | Mean | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated |
|------------------- -------------------- |---------:|------:|--------:|--------:|------:|----------:|
| GetProcesses \after\CoreRun.exe | 4.948 ms | 1.00 | 78.4314 | 19.6078 | - | 621 KB |
| GetProcesses \before\CoreRun.exe | 4.916 ms | 1.00 | 80.0000 | 20.0000 | - | 619 KB |
| | | | | | | |
| GetProcessesByName \after\CoreRun.exe | 4.912 ms | 1.00 | 80.0000 | 20.0000 | - | 619 KB |
| GetProcessesByName \before\CoreRun.exe | 4.903 ms | 1.00 | 80.0000 | 20.0000 | - | 619 KB |

@ghost

ghost commented Dec 7, 2020

Copy link
Copy Markdown

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

Issue Details

Contributes to #45315

Author:adamsitnik
Assignees:-
Labels:

area-System.Diagnostics.Process, tenet-performance

Milestone:6.0.0

@ghostghost locked as resolved and limited conversation to collaborators Apr 24, 2021
@jkotas

Copy link
Copy Markdown
Member

@adamsitnik Now that ArrayPool was fixed to pool unlimited size arrays, I think this PR can be resurrect and updated to use ArrayPool unconditionally.

@adamsitnikadamsitnik reopened this Aug 16, 2021
@adamsitnik
adamsitnik requested a review from jkotasAugust 16, 2021 09:19
@adamsitnik

Copy link
Copy Markdown
MemberAuthor

Now that ArrayPool was fixed to pool unlimited size arrays, I think this PR can be resurrect and updated to use ArrayPool unconditionally.

@jkotas done, PTAL

@adamsitnikadamsitnik modified the milestones: 6.0.0, 7.0.0Aug 16, 2021
adamsitnikand others added 2 commits August 17, 2021 20:09
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
@adamsitnik
adamsitnikforce-pushed the NtProcessInfoHelperRemoveCache branch from 5e56129 to fc4378fCompareAugust 17, 2021 18:23
@adamsitnik
adamsitnik requested a review from jkotasAugust 17, 2021 18:27
@jkotas

Copy link
Copy Markdown
Member

It looks good to me. I think it would be useful to verify that there is advantage in using the array pool instead of a simpler NativeMemory.Alloc in this situation - #45690 (comment) .

@adamsitnik

Copy link
Copy Markdown
MemberAuthor

I think it would be useful to verify that there is advantage in using the array pool instead of a simpler NativeMemory.Alloc

I did some measurements using modified benchmarks from performance repo:

Details
[Benchmark]publicvoidGetProcessesByName(){foreach(varprocessinProcess.GetProcessesByName(_nonExistingName)){process.Dispose();}}[Benchmark(OperationsPerInvoke=10*24)]publicvoidGetProcesses_Parallel(){Parallel.For(0,24, _ =>// my PC has 24 cores{for(inti=0;i<10;i++){foreach(varprocessinProcess.GetProcesses()){process.Dispose();}}});}[Benchmark(OperationsPerInvoke=10*24)]publicvoidGetProcessesByName_Parallel(){Parallel.For(0,24, _ =>{for(inti=0;i<10;i++){foreach(varprocessinProcess.GetProcessesByName(_nonExistingName)){process.Dispose();}}});}

And the results were following:

BenchmarkDotNet=v0.13.0.1559-nightly, OS=Windows 10.0.19043.1165 (21H1/May2021Update) AMD Ryzen Threadripper PRO 3945WX 12-Cores, 1 CPU, 24 logical and 12 physical cores .NET SDK=6.0.100-rc.1.21417.19 
MethodToolchainMeanRatioGen 0Gen 1Gen 2Allocated
GetProcesses\alignedAlloc\corerun.exe4.791 ms1.05---477 KB
GetProcesses\arrayPool\corerun.exe4.508 ms1.0055.555618.5185-475 KB
GetProcessesByName\alignedAlloc\corerun.exe4.658 ms1.0546.875015.6250-475 KB
GetProcessesByName\arrayPool\corerun.exe4.456 ms1.0046.875015.6250-473 KB
GetProcesses_Parallel\alignedAlloc\corerun.exe1.154 ms0.6658.333316.66674.1667476 KB
GetProcesses_Parallel\arrayPool\corerun.exe1.763 ms1.0062.500020.83334.1667484 KB
GetProcessesByName_Parallel\alignedAlloc\corerun.exe1.098 ms0.6058.333316.66674.1667475 KB
GetProcessesByName_Parallel\arrayPool\corerun.exe1.843 ms1.0062.500016.66674.1667484 KB

AlignedAlloc seems to perform worse for single-threaded (5%), but better for parallel usage (30-40%).
With AlignedAlloc the code is also simpler.

@stephentoub@jkotas I don't have a strong opinion here. What are your thoughts on this?

@jkotas

Copy link
Copy Markdown
Member

AlignedAlloc

Nit: It can be just NativeLibrary.Alloc. It guarantees sufficient alignment. AlignedAlloc is unnecessary.

What are your thoughts on this?

I would lean towards using NativeLibrary.Alloc. I think it will give lower high-memory watermark for some common usage patterns of this API. I think minimizing working set is more important than saving cycles for this API.

I do not have a strong opinion on this either. Thank you for collecting the numbers!

@adamsitnik

Copy link
Copy Markdown
MemberAuthor

NativeLibrary.Alloc

I've switched to NativeLibrary.Alloc and ensured that perf characteristics don't look worse than AlignedAlloc.

MethodToolchainMeanRatioGen 0Gen 1Gen 2Allocated
GetProcesses\alignedAlloc\corerun.exe2,991.6 us1.08---405 KB
GetProcesses\alloc\corerun.exe2,903.3 us1.04---397 KB
GetProcesses\arrayPool\corerun.exe2,776.7 us1.0047.058811.7647-395 KB
GetProcessesByName\alignedAlloc\corerun.exe2,933.2 us1.0641.666710.4167-403 KB
GetProcessesByName\alloc\corerun.exe2,805.3 us1.0137.500012.5000-395 KB
GetProcessesByName\arrayPool\corerun.exe2,776.5 us1.0041.666710.4167-394 KB
GetProcesses_Parallel\alignedAlloc\corerun.exe1,049.0 us0.7054.166712.50004.1667404 KB
GetProcesses_Parallel\alloc\corerun.exe963.5 us0.6445.833312.50004.1667397 KB
GetProcesses_Parallel\arrayPool\corerun.exe1,521.2 us1.0050.000012.50004.1667395 KB
GetProcessesByName_Parallel\alignedAlloc\corerun.exe982.3 us0.6450.00008.33334.1667402 KB
GetProcessesByName_Parallel\alloc\corerun.exe1,035.7 us0.6854.166720.83334.1667400 KB
GetProcessesByName_Parallel\arrayPool\corerun.exe1,544.2 us1.0050.000012.50004.1667393 KB

@jkotas thank you for a lot of good hints and great discussion!

@jkotasjkotas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks

@adamsitnik
adamsitnik merged commit 17e92db into dotnet:mainAug 19, 2021
@adamsitnik
adamsitnik deleted the NtProcessInfoHelperRemoveCache branch August 19, 2021 17:24
Sign up for freeto 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

@adamsitnik@stephentoub@jkotas@eiriktsarpalis