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

HttpClient use ValueTask internally #31623

Closed

Conversation

benaadams
Copy link
Member

@benaadams benaadams commented Feb 2, 2020

Test code for HttpClient with http

master (Task)

Threads: 1, Request/s: 11,478.0, Time: 87,122 ms, Allocated/Request: 3,200
Threads: 2, Request/s: 24,753.7, Time: 40,398 ms, Allocated/Request: 3,200
Threads: 3, Request/s: 40,130.3, Time: 24,918 ms, Allocated/Request: 3,200
Threads: 4, Request/s: 50,418.6, Time: 19,833 ms, Allocated/Request: 3,199

PR (ValueTask) SET DOTNET_SYSTEM_THREADING_POOLASYNCVALUETASKS=0

Threads: 1, Request/s: 11,308.8, Time: 88,426 ms, Allocated/Request: 3,200
Threads: 2, Request/s: 24,235.0, Time: 41,262 ms, Allocated/Request: 3,200
Threads: 3, Request/s: 39,305.8, Time: 25,441 ms, Allocated/Request: 3,200
Threads: 4, Request/s: 50,888.5, Time: 19,650 ms, Allocated/Request: 3,199

PR (ValueTask) SET DOTNET_SYSTEM_THREADING_POOLASYNCVALUETASKS=1

Threads: 1, Request/s: 11,424.4, Time: 87,531 ms, Allocated/Request: 3,024
Threads: 2, Request/s: 25,417.1, Time: 39,343 ms, Allocated/Request: 3,024
Threads: 3, Request/s: 41,144.7, Time: 24,304 ms, Allocated/Request: 3,024
Threads: 4, Request/s: 52,013.2, Time: 19,225 ms, Allocated/Request: 3,025
"configProperties": {
  "System.GC.Server": true,
  "System.GC.HeapHardLimit": 20971520
}

@stephentoub
Copy link
Member

still seems bucket loads.

Having trouble parsing this... bucket?

@stephentoub
Copy link
Member

Testing SET DOTNET_SYSTEM_THREADING_POOLASYNCVALUETASKS=1

👍

@benaadams
Copy link
Member Author

still seems bucket loads.

Having trouble parsing this... bucket?

A large amount; requiring several buckets; might be a British colloquialism 😄

@stephentoub
Copy link
Member

Oh! :-) I thought you were saying something was loading.

@stephentoub
Copy link
Member

Can you share the code you're using?

@benaadams
Copy link
Member Author

Can you share the code you're using?

Still playing with it, aside from memory, bit of a (small) gain when single threaded, looking at multithreaded bit of a (small) loss when mutli-threaded (assume contention) https://gist.github.com/benaadams/cd2969e13c582ab4070489b5c585024e (client and server)

I thought HttpClient was a good sample candidate (being not propriety, easy to share results) since it has many StateMachineBoxes

image

However, the allocations are still heavy from elsewhere

image

And can't get rid of all of them due to the public api being Task based :-/

Going to see what happens when going a bit deeper e.g. requesting https so including sslstream in the pipeline

@benaadams
Copy link
Member Author

benaadams commented Feb 3, 2020

@stephentoub current code for HttpClient with http

master (Task)

Threads: 1, Request/s: 11,478.0, Time: 87,122 ms, Allocated/Request: 3,200
Threads: 2, Request/s: 24,753.7, Time: 40,398 ms, Allocated/Request: 3,200
Threads: 3, Request/s: 40,130.3, Time: 24,918 ms, Allocated/Request: 3,200
Threads: 4, Request/s: 50,418.6, Time: 19,833 ms, Allocated/Request: 3,199

PR (ValueTask) SET DOTNET_SYSTEM_THREADING_POOLASYNCVALUETASKS=0

Threads: 1, Request/s: 11,308.8, Time: 88,426 ms, Allocated/Request: 3,200
Threads: 2, Request/s: 24,235.0, Time: 41,262 ms, Allocated/Request: 3,200
Threads: 3, Request/s: 39,305.8, Time: 25,441 ms, Allocated/Request: 3,200
Threads: 4, Request/s: 50,888.5, Time: 19,650 ms, Allocated/Request: 3,199

PR (ValueTask) SET DOTNET_SYSTEM_THREADING_POOLASYNCVALUETASKS=1

Threads: 1, Request/s: 11,424.4, Time: 87,531 ms, Allocated/Request: 3,024
Threads: 2, Request/s: 25,417.1, Time: 39,343 ms, Allocated/Request: 3,024
Threads: 3, Request/s: 41,144.7, Time: 24,304 ms, Allocated/Request: 3,024
Threads: 4, Request/s: 52,013.2, Time: 19,225 ms, Allocated/Request: 3,025
"configProperties": {
  "System.GC.Server": true,
  "System.GC.HeapHardLimit": 20971520
}

@benaadams benaadams marked this pull request as ready for review February 3, 2020 03:54
@benaadams benaadams requested review from scalablecory, stephentoub and wfurt and removed request for scalablecory and stephentoub February 3, 2020 03:54
@stephentoub
Copy link
Member

test code

Can you:

  • set HttpClient.Timeout to infinite
  • pass ResponseHeadersRead to SendAsync

That should reduce some of the noise.

On top of that, you could use the base HttpMessageInvoker instead of the derived HttpClient.

@benaadams
Copy link
Member Author

On top of that, you could use the base HttpMessageInvoker instead of the derived HttpClient.

Changing to
new HttpMessageInvoker(new SocketsHttpHandler(), disposeHandler: false) drops allocs by about 1Kb but also throughput for some reason. Also I'm right in thinking the other changes don't apply as with the Invoker they are HttpClient only?

Will reboot and restart, just incase its caused overnight detritus

@stephentoub
Copy link
Member

also throughput for some reason

I'd guess because you're doing 14 1-byte reads on the response stream. Previously HttpClient was buffering the whole response, so your 1-byte reads were all against a memory stream.

@stephentoub
Copy link
Member

@benaadams, thanks for this. I'm going to close this for now. Given that there's a small regression when the environment variable isn't set, we should wait to do something like this until it's clearer what the future of the setting will be.

@karelz karelz added this to the 5.0.0 milestone Aug 18, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Dec 10, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants