Add Multithread perf test#1222
Conversation
|
@stephentoub is this the correct way to use Parallel.For for maximum throughput? File |
I expect that'll be about as good as you can get with it, assuming nothing else is taking up thread pool threads while this runs. There will be a small amount of overhead in getting started, but it shouldn't be measurable assuming enough work is done in the body. |
|
4 Core desktop
Single threaded Multi threaded |
b06a513 to
ff8131c
Compare
| "netcoreapp1.0": { | ||
| "dependencies": { | ||
| "Microsoft.NETCore.App": { | ||
| "version": "1.0.1-*", |
There was a problem hiding this comment.
Nice catch. Easy to miss things like that in major PRs.
There was a problem hiding this comment.
Wasn't sure it would work; BenchMarkDotnet currently doesn't like netcoreapp1.1
| "DNT: 1\r\n" + | ||
| "Referer: http://stackoverflow.com/?tab=month\r\n" + | ||
| "Pragma: no-cache\r\n" + | ||
| "Cookie: prov=20629ccd-8b0f-e8ef-2935-cd26609fc0bc; __qca=P0-1591065732-1479167353442; _ga=GA1.2.1298898376.1479167354; _gat=1; sgt=id=9519gfde_3347_4762_8762_df51458c8ec2; acct=t=why-is-%e0%a5%a7%e0%a5%a8%e0%a5%a9-numeric&s=why-is-%e0%a5%a7%e0%a5%a8%e0%a5%a9-numeric\r\n\r\n"; |
There was a problem hiding this comment.
Nit: Share the request data in some static class in case we ever change anything with them.
| private static readonly byte[] _unicodePipelinedRequests = Encoding.ASCII.GetBytes(string.Concat(Enumerable.Repeat(unicodeRequest, Pipelining))); | ||
| private static readonly byte[] _unicodeRequest = Encoding.ASCII.GetBytes(unicodeRequest); | ||
|
|
||
| private static readonly int ThreadCount = Environment.ProcessorCount; |
There was a problem hiding this comment.
For convenience, can we print this?
There was a problem hiding this comment.
Added to Program.cs
ff8131c to
d6b446e
Compare
|
Updated for BenchmarkDotNet to 0.10.1 @halter73 @CesarBS @pakrym worth the upgrade; is 1.1.0 and new memory diag built in New output (minus a few columns); note last column |
| public static readonly byte[] PlaintextPipelinedRequests = Encoding.ASCII.GetBytes(string.Concat(Enumerable.Repeat(plaintextRequest, Pipelining))); | ||
| public static readonly byte[] PlaintextRequest = Encoding.ASCII.GetBytes(plaintextRequest); | ||
|
|
||
| public static readonly byte[] LiveaspnentPipelinedRequests = Encoding.ASCII.GetBytes(string.Concat(Enumerable.Repeat(liveaspnetRequest, Pipelining))); |
There was a problem hiding this comment.
nit: rename aspnetnt -> AspNet
| public static readonly byte[] PlaintextRequest = Encoding.ASCII.GetBytes(plaintextRequest); | ||
|
|
||
| public static readonly byte[] LiveaspnentPipelinedRequests = Encoding.ASCII.GetBytes(string.Concat(Enumerable.Repeat(liveaspnetRequest, Pipelining))); | ||
| public static readonly byte[] LiveaspnentRequest = Encoding.ASCII.GetBytes(liveaspnetRequest); |
There was a problem hiding this comment.
nit: rename aspnetnt -> AspNet
|
|
||
| private const string plaintextRequest = "GET /plaintext HTTP/1.1\r\nHost: www.example.com\r\n\r\n"; | ||
|
|
||
| private const string liveaspnetRequest = "GET https://live.asp.net/ HTTP/1.1\r\n" + |
There was a problem hiding this comment.
uber nit: why aspnet and not AspNet?
There was a problem hiding this comment.
Just deleted the . from the domain name; going on the important words being Site; Request and Pipelined wasn't thinking too hard about it :)
9a19282 to
264249a
Compare
264249a to
40bb880
Compare
|
Renamed |
|
@benaadams which part of kestrel code does this benchmark vs single-threaded version? |
|
@pakrym same code, just maxes it out across cores rather than single core; it should be embarrassingly parallel; though the increase I am seeing isn't as much as x N cores - which may be interesting |
|
This doesn't test any kind of contention. It might be more useful to have a test that keeps the producer going during consumption to test contention acquiring SocketInput's _sync lock. Maybe you could use the threadpool to dispatch calls to InsertData and ensure that there is enough data always in the buffer to prevent the consumer from ever catching up with the producer. By looking at the return values of TakeStartLine and TakeMessageHeaders it should be possible to see if the consumer ever stalls. |
Results on 16 core (32 HT) Server
Single threaded
Multi threaded