Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Port https://github.com/dotnet/coreclr/pull/2724 to rc2 #2733

Merged
merged 4 commits into from
Jan 20, 2016

Conversation

stephentoub
Copy link
Member

No description provided.

stephentoub and others added 4 commits January 19, 2016 17:12
Stream.XxAsync are currently implemented as a wrapper around Stream.Begin/EndXx.  When a derived class overrides XxAsync to do its own async implementation, there's no issue.  When a derived class overrides Begin/EndXx but not XxAsync, there's no issue (the base implementation does what it needs to do, wrapping Begin/EndXx).  However, if the derived implementation doesn't override either XxAsync or Begin/EndXx, there are a few issues.

First, there's unnecessary cost.  The base Begin/EndXx methods queue a Task to call the corresponding Read/Write method.  But then the XxAsync method create another Task to wrap the Begin/End method invocation.  This means we're allocating and completing two tasks, when we only needed to do one.

Second, task wait inlining is affected.  Because Read/WriteAsync aren't returning the original queued delegate-backed task but rather a promise task, Wait()'ing on the returned task blocks until the operation completes on another thread.  If the original delegate-backed task were returned, then Wait()'ing on the task could potentially "inline" its execution onto the current thread.

Third, there's unnecessary blocking if there are other outstanding async operations on the instance.  Since Begin/EndXx were introduced, they track whether an operation is in progress, and subsequent calls to BeginXx while an operation is in progress blocks synchronously.  Since Read/WriteAsync just wrap the virtual Begin/End methods, they inherit this behavior.

This commit addresses all three issues for CoreCLR.  The Begin/EndXx methods aren't exposed from Stream in the new contracts, and as a result outside of mscorlib we don't need to be concerned about these methods being overridden.  Thus, the commit adds an optimized path that simply returns the original delegate-backed task rather than wrapping it.  This avoids the unnecessary task overheads and duplication, and it enables wait inlining if someone happens to wait on it.  Further, since we're no longer subject to the behaviors of Begin/End, we can change the serialization to be done asynchronously rather than synchronously.
- Remove older reflection-based detection of overrides from SyncStream
- Remove Tuple allocation from RunReadWriteTaskWhenReady
- Fix spelling of Overridden
- Add a few comments
@ellismg
Copy link

ellismg commented Jan 20, 2016

@dotnet-bot Test Ubuntu x64 Release Build and Test Please (unpacker token too long error, fixed on the machine).

@ellismg
Copy link

ellismg commented Jan 20, 2016

The Windows_NT x64 Debug Build and Test failure is due to an a race condition where we can deadlock when trying to run finalizers during shutdown. I am going to disable this test until dotnet/corefx#5205 is addressed (however perhaps the test should be updated such that it always works).

@ellismg
Copy link

ellismg commented Jan 20, 2016

@dotnet-bot Test Windows_NT x64 Debug Build and Test Please

@leecow leecow added this to the 1.0.0-rc2 milestone Jan 20, 2016
ellismg added a commit that referenced this pull request Jan 20, 2016
@ellismg ellismg merged commit 8485239 into dotnet:release/1.0.0-rc2 Jan 20, 2016
@stephentoub stephentoub deleted the port2724 branch January 26, 2016 03:41
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants