Releases: alanmcgovern/ReusableTasks
Releases · alanmcgovern/ReusableTasks
v4.0.0
Updates
- Downgraded the dependency on System.Runtime.CompilerServices.Unsafe from 6.0.0 to 4.5.0.
Full Changelog: release-v3.0.0...release-v4.0.0
v3.0.0
What's Changed
- Fastpath by @alanmcgovern in #7 . When a ReusableTask continues from another ReusableTask we can pass the StateMachineCache object directly as the continuation to avoid creating an Action which points to the StateMachineCache. This optimisation works for ReusableTask -> ReusableTask as well as ReusableTask -> ReusableTask and ReusableTask -> ReusableTask.
Before
Method | Concurrency | Depth | Iterations | Mean | Error | StdDev | Median | Gen 0 | Gen 1 | Allocated |
---|---|---|---|---|---|---|---|---|---|---|
ReusableTask | 1 | 500 | 1000 | 64.40 ms | 4.009 ms | 11.757 ms | 61.14 ms | - | - | 32 KB |
ReusableTaskInt | 1 | 500 | 1000 | 40.76 ms | 3.133 ms | 8.733 ms | 37.86 ms | - | - | 32 KB |
ValueTaskInt | 1 | 500 | 1000 | 65.22 ms | 1.281 ms | 2.140 ms | 65.50 ms | 6300.0000 | 100.0000 | 51,452 KB |
ReusableTask | 4 | 500 | 1000 | 91.19 ms | 3.628 ms | 10.698 ms | 92.22 ms | - | - | 32 KB |
ReusableTaskInt | 4 | 500 | 1000 | 57.23 ms | 2.273 ms | 6.630 ms | 57.10 ms | - | - | 127 KB |
ValueTaskInt | 4 | 500 | 1000 | 154.20 ms | 3.067 ms | 5.835 ms | 154.74 ms | 22250.0000 | 1000.0000 | 182,428 KB |
After
Method | Concurrency | Depth | Iterations | Mean | Error | StdDev | Median | Gen 0 | Gen 1 | Allocated |
---|---|---|---|---|---|---|---|---|---|---|
ReusableTask | 1 | 500 | 1000 | 41.91 ms | 1.705 ms | 4.667 ms | 41.04 ms | - | - | 32 KB |
ReusableTaskInt | 1 | 500 | 1000 | 34.96 ms | 5.059 ms | 14.917 ms | 33.78 ms | - | - | 32 KB |
ValueTaskInt | 1 | 500 | 1000 | 61.91 ms | 3.413 ms | 9.738 ms | 56.92 ms | 6000.0000 | - | 49,869 KB |
ReusableTask | 4 | 500 | 1000 | 55.24 ms | 2.077 ms | 6.124 ms | 54.68 ms | - | - | 32 KB |
ReusableTaskInt | 4 | 500 | 1000 | 51.82 ms | 2.425 ms | 7.111 ms | 51.74 ms | - | - | 127 KB |
ValueTaskInt | 4 | 500 | 1000 | 157.49 ms | 3.112 ms | 8.199 ms | 157.46 ms | 22500.0000 | 1000.0000 | 182,908 KB |
Full Changelog: release-v2.0.3...release-v3.0.0
v2.0.3
General
default (ReusableTask)
anddefault (ReusableTask<T>)
now represent a successfully completed task, matching the semantics ofValueTask<T>
.- Internal caches are now protected with spinlocks instead of full locks. These are typically low contention and so benefit from the improved performance of a spinlock.
- Improved performance executing the continuation from an asynchronously completed
ReusableTask
orReusableTask<T>
Full Changelog: release-v2.0.2...release-v2.0.3
v2.0.2
General
- Use the UnsafeQueueUserWorkItem(IThreadPoolWorkItem) overload to provide allocation free enqueuing to the ThreadPool.
v2.0.1
General
Bundle a C# source file with the nuget to replace the method builder used for async void
methods so it uses the allocation-free support provided by ReusableTask. This can be disabled by adding <DisableAsyncVoidOptimisation>true</DisableAsyncVoidOptimisation>
to the csproj which references the nuget package.
Each csproj must directly reference the nuget to activate this optimisation.
v2.0.0
General
- Removed the TrySet methods from ReusableTaskCompletionSource. As this is a reusable object, you must call SetResult, SetException or SetCancelled exactly once for every 'await' invocation. The TrySet methods may tempt someone into calling
'TrySetResult' and 'TrySetCanceled', which would result in two different results being set.
v1.0.7
General
- Add a helper method
ReusableTask.FromResult
so synchronous methods can be more easily implemented.
v1.0.6
General
- No change from the previous beta. Just releasing it as the final stable build after removing the 'beta' tag.
v1.0.6-beta
General
- Tweak the core to further improve how concurrent 'SetResult' and 'IsCompleted' invocations are handled. This improves on the changes released with 1.0.5 and attempts to resolve the issues once and for all.
v1.0.5
General
- Fixed a race condition introduced by 37f42fa due to the new TrySet code. The 'HasValue' flag was being set before the value was set, which meant that an
await
on another thread could complete before the value was actually stored in the field. This could lead to a number of odd behaviours.