Last active
April 19, 2017 10:39
-
-
Save mgravell/c570ec103afe6960426ba2de45ff61a1 to your computer and use it in GitHub Desktop.
async; ValueTask vs Task
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Objective: compare Task<T> vs ValueTask<T> in a scenario that should | |
be ideal for ValueTask<T> - non-trivial results, but usually (always) | |
already completed. | |
Hypothesis: ValueTask<T> should be more efficient, as it does not (in | |
the "already completed" case) involve allocation. | |
Methodology: create a test rig that computes a number using multiple | |
nested roll-up operations, comparing sync vs async-Task<T> vs async-ValueTask<T>; | |
use "async"/"await" for the rollups in the async cases. Run all tests using | |
BenchmarkDotNet from command-line in release mode. It is expected that both | |
Task<T> and ValueTask<T> will have some overhead compared to non-async version. | |
Follow-up: added "HandCranked" versions that seek to avoid the await machinery. | |
Faster, but ugly as sin. | |
Code: https://github.com/mgravell/protobuf-net/tree/async/src/TheAwaitingGame | |
Results: ValueTask<T> appears to take *longer* than Task<T>; update - but it allocates far less: | |
-------------------------------------------- | |
``` | |
> dotnet run -c Release -f net462 | |
Total time: 00:03:57 (237.7 sec) | |
// * Summary * | |
BenchmarkDotNet=v0.10.3.111-nightly, OS=Windows 10.0.14393 | |
Processor=Intel(R) Core(TM) i7-5930K CPU 3.50GHz, ProcessorCount=12 | |
Frequency=3416975 Hz, Resolution=292.6565 ns, Timer=TSC | |
dotnet cli version=1.0.3 | |
[Host] : .NET Core 4.6.25009.03, 64bit RyuJIT | |
Job-LKSOIG : .NET Core 4.6.25009.03, 64bit RyuJIT | |
Force=False | |
Method | Mean | StdErr | StdDev | Op/s | Gen 0 | Allocated | | |
------------------------------- |-----------:|----------:|----------:|---------:|-------:|----------:| | |
Sync | 10.9782 us | 0.0168 us | 0.0580 us | 91089.95 | - | 0 kB | | |
TaskAsync | 17.7219 us | 0.0532 us | 0.1919 us | 56427.3 | 3.8625 | 24.25 kB | | |
TaskCheckedAsync | 17.5696 us | 0.0480 us | 0.1732 us | 56916.64 | 3.8625 | 24.25 kB | | |
ValueTaskAsync | 21.5139 us | 0.0526 us | 0.1895 us | 46481.58 | - | 0 kB | | |
ValueTaskWrappedAsync | 20.4348 us | 0.0396 us | 0.1371 us | 48936.02 | 0.6333 | 3.99 kB | | |
ValueTaskDecimalReferenceAsync | 17.4158 us | 0.0562 us | 0.2025 us | 57419.19 | 1.5458 | 9.7 kB | | |
ValueTaskCheckedAsync | 18.8079 us | 0.0203 us | 0.0732 us | 53169.22 | - | 0 kB | | |
HandCrankedAsync | 15.1644 us | 0.0283 us | 0.1020 us | 65944.09 | - | 0 kB | | |
AssertCompletedAsync | 16.3290 us | 0.1084 us | 0.4057 us | 61240.56 | - | 0 kB | | |
TaskDoubleAsync | 15.2432 us | 0.0418 us | 0.1506 us | 65603.14 | 3.4750 | 21.82 kB | | |
ValueTaskDoubleAsync | 17.1229 us | 0.1955 us | 0.8059 us | 58401.46 | - | 0 kB | | |
``` | |
-------------------------------------------- | |
``` | |
> dotnet run -c Release -f netcoreapp1.1 | |
Total time: 00:01:23 (83.08 sec) | |
// * Summary * | |
BenchmarkDotNet=v0.10.3.0, OS=Microsoft Windows 10.0.15063 | |
Processor=Intel(R) Core(TM) i7-7700HQ CPU 2.80GHz, ProcessorCount=8 | |
Frequency=2742190 Hz, Resolution=364.6720 ns, Timer=TSC | |
dotnet cli version=1.0.2 | |
[Host] : .NET Core 4.6.25009.03, 64bit RyuJIT | |
DefaultJob : .NET Core 4.6.25009.03, 64bit RyuJIT | |
Method | Mean | StdDev | Gen 0 | Allocated | | |
----------------- |---------- |---------- |---------- |---------- | | |
Sync | 3.0868 ms | 0.0634 ms | - | 68 B | | |
TaskAsync | 4.7674 ms | 0.0915 ms | 1796.8750 | 6.06 MB | | |
ValueTaskAsync | 5.7727 ms | 0.0591 ms | - | 135 B | | |
HandCrankedAsync | 4.6280 ms | 0.0449 ms | - | 135 B | | |
``` |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment