New dotnet version means new features and improvements. There is a nice update to the HttpClient
class in .NET 10.
Content buffering
To understand the improvement, we have to distinguish between two types:
- We know upfront how much data we will receive (so the
Content-Length
header is set). - We don't know how much data we will receive (so the
Content-Length
header is not set).
The improvement is for the latter case. When streaming a response, it can happen that the buffer has to be resized multiple times. This can be expensive, especially if the response is large. The new HttpClient
implementation in .NET 10 uses a pooled approach to reduce the overhead or creating new buffers.
Here are some of the improvements (details see: https://github.com/dotnet/runtime/pull/109642):
| Method | Toolchain | Length | Mean | Ratio | Allocated | Alloc Ratio |
|------------------|-----------|------------|------------------|-------|----------------|--------------|
| GetByteArrayAsync| main | 10000 | 1,114.6 ns | 1.00 | 10.81 KB | 1.00 |
| GetByteArrayAsync| pr | 10000 | 994.3 ns | 0.89 | 10.84 KB | 1.00 |
| GetAsync | main | 10000 | 1,284.7 ns | 1.00 | 28.93 KB | 1.00 |
| GetAsync | pr | 10000 | 1,018.1 ns | 0.79 | 10.84 KB | 0.37 |
| GetByteArrayAsync| main | 100000 | 28,454.2 ns | 1.00 | 98.73 KB | 1.00 |
| GetByteArrayAsync| pr | 100000 | 28,038.7 ns | 0.99 | 98.76 KB | 1.00 |
| GetAsync | main | 100000 | 31,313.5 ns | 1.00 | 251.58 KB | 1.00 |
| GetAsync | pr | 100000 | 28,186.0 ns | 0.90 | 98.76 KB | 0.39 |
| GetByteArrayAsync| main | 1000000 | 127,633.7 ns | 1.00 | 978.16 KB | 1.00 |
| GetByteArrayAsync| pr | 1000000 | 110,941.5 ns | 0.87 | 978.11 KB | 1.00 |
| GetAsync | main | 1000000 | 151,716.7 ns | 1.00 | 2032.28 KB | 1.00 |
| GetAsync | pr | 1000000 | 110,231.7 ns | 0.73 | 978.1 KB | 0.48 |
| GetByteArrayAsync| main | 10000000 | 1,946,940.2 ns | 1.00 | 9768.06 KB | 1.00 |
| GetByteArrayAsync| pr | 10000000 | 1,113,033.0 ns | 0.57 | 9769.06 KB | 1.00 |
| GetAsync | main | 10000000 | 2,720,321.2 ns | 1.04 | 32553.84 KB | 1.00 |
| GetAsync | pr | 10000000 | 1,137,477.7 ns | 0.43 | 9768.88 KB | 0.30 |
| GetByteArrayAsync| main | 100000000 | 21,216,153.0 ns | 1.00 | 97657.44 KB | 1.00 |
| GetByteArrayAsync| pr | 100000000 | 17,026,034.7 ns | 0.80 | 97657.69 KB | 1.00 |
| GetAsync | main | 100000000 | 25,177,538.4 ns | 1.00 | 260446.05 KB | 1.00 |
| GetAsync | pr | 100000000 | 16,487,114.6 ns | 0.66 | 97657.69 KB | 0.37 |