Skip to content

Don't use callbacks when performing sync IO with async handles#126845

Open
Copilot wants to merge 19 commits into
mainfrom
copilot/remove-callbacks-sync-io
Open

Don't use callbacks when performing sync IO with async handles#126845
Copilot wants to merge 19 commits into
mainfrom
copilot/remove-callbacks-sync-io

Conversation

Copilot AI commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

Description

When performing synchronous I/O on async file handles (FILE_FLAG_OVERLAPPED), RandomAccess.Windows.cs previously used ThreadPoolBoundHandle.UnsafeAllocateNativeOverlapped with an IOCompletionCallback and a custom CallbackResetEvent class that tracked a reference count to handle the race between the IOCP callback and the caller's GetOverlappedResult.

This callback path is unnecessary. Setting the low-order bit of hEvent in the OVERLAPPED structure prevents the I/O completion from being queued to the completion port, eliminating the callback.

This reduces complexity and allocations, preserves managed wait behavior, fixes correctness issues in both error handling and exceptional wait paths, and hardens handle lifetime safety in the sync-over-async path.

Copilot AI requested review from Copilot and removed request for Copilot April 13, 2026 17:28
Copilot AI linked an issue Apr 13, 2026 that may be closed by this pull request
…vent for sync IO with async handles

Instead of using ThreadPoolBoundHandle callbacks and reference counting when
performing synchronous IO with async file handles, allocate the NativeOverlapped
directly via NativeMemory and set the low-order bit of hEvent to suppress I/O
completion port notifications. This eliminates the CallbackResetEvent class,
the s_callback field, and the AllocateCallback/GetNativeOverlappedForAsyncHandle
methods, reducing allocations and complexity.

Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/d7a61400-c63f-401a-9503-0313459af6f7

Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Copilot AI requested review from Copilot and removed request for Copilot April 13, 2026 17:58
Copilot AI changed the title [WIP] Remove callbacks for sync IO operations with async handles Don't use callbacks when performing sync IO with async handles Apr 13, 2026
Copilot AI requested a review from adamsitnik April 13, 2026 18:04
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/area-system-io
See info in area-owners.md if you want to be subscribed.

@adamsitnik adamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot please address my feedback (nits)

Comment thread src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Windows.cs Outdated
Comment thread src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Windows.cs Outdated
…appedWithEventHandle

Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/bcdd8838-718e-4561-abf4-90c9c2deb905

Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Copilot AI requested review from Copilot and removed request for Copilot April 14, 2026 05:47
Copilot AI requested a review from adamsitnik April 14, 2026 05:48
@adamsitnik adamsitnik marked this pull request as ready for review April 14, 2026 05:53
Copilot AI review requested due to automatic review settings April 14, 2026 05:53

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.

@adamsitnik adamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes LGTM, the perf is much better despite still using ManualResetEvent:

(managed_cached is the PR)

BenchmarkDotNet v0.16.0-nightly.20260302.459, Windows 11 (10.0.26200.8390/25H2/2025Update/HudsonValley2)
AMD Ryzen Threadripper PRO 3945WX 12-Cores 3.99GHz, 1 CPU, 24 logical and 12 physical cores
Memory: 63.86 GB Total, 32.62 GB Available
.NET SDK 11.0.100-preview.5.26255.101
  [Host]     : .NET 11.0.0 (11.0.0-preview.5.26255.101, 11.0.26.25601), X64 RyuJIT x86-64-v3
Method Toolchain fileSize userBufferSize options Mean Ratio Allocated
Read \main\corerun.exe 1024 1024 None 145.7 us 1.00 4360 B
Read \main\corerun.exe 1024 1024 Asynchronous 173.9 us 1.00 4576 B
Read \managed_cached\corerun.exe 1024 1024 Asynchronous 156.9 us 0.90 4464 B
Read \native_cached\corerun.exe 1024 1024 Asynchronous 154.6 us 0.89 4440 B
Write \main\corerun.exe 1024 1024 None 609.2 us 1.00 4360 B
Write \main\corerun.exe 1024 1024 Asynchronous 639.3 us 1.00 4577 B
Write \managed_cached\corerun.exe 1024 1024 Asynchronous 627.9 us 0.98 4465 B
Write \native_cached\corerun.exe 1024 1024 Asynchronous 623.3 us 0.98 4441 B
Read \main\corerun.exe 1048576 512 None 779.2 us 1.00 4361 B
Read \main\corerun.exe 1048576 512 Asynchronous 2,756.3 us 1.00 49460 B
Read \managed_cached\corerun.exe 1048576 512 Asynchronous 1,262.3 us 0.46 4466 B
Read \native_cached\corerun.exe 1048576 512 Asynchronous 1,113.6 us 0.40 4442 B
Write \main\corerun.exe 1048576 512 None 7,438.8 us 1.00 4365 B
Write \main\corerun.exe 1048576 512 Asynchronous 7,788.8 us 1.00 49470 B
Write \managed_cached\corerun.exe 1048576 512 Asynchronous 7,507.1 us 0.96 4473 B
Write \native_cached\corerun.exe 1048576 512 Asynchronous 7,387.7 us 0.95 4449 B
Read \main\corerun.exe 1048576 4096 None 709.8 us 1.00 241 B
Read \main\corerun.exe 1048576 4096 Asynchronous 2,929.2 us 1.00 45340 B
Read \managed_cached\corerun.exe 1048576 4096 Asynchronous 1,235.6 us 0.42 346 B
Read \native_cached\corerun.exe 1048576 4096 Asynchronous 1,049.8 us 0.36 322 B
Write \main\corerun.exe 1048576 4096 None 7,197.4 us 1.00 245 B
Write \main\corerun.exe 1048576 4096 Asynchronous 7,838.3 us 1.00 45350 B
Write \managed_cached\corerun.exe 1048576 4096 Asynchronous 7,351.9 us 0.94 353 B
Write \native_cached\corerun.exe 1048576 4096 Asynchronous 7,477.0 us 0.96 329 B
Read \main\corerun.exe 104857600 4096 None 82,969.7 us 1.00 352 B
Read \main\corerun.exe 104857600 4096 Asynchronous 329,198.7 us 1.00 4506328 B
Read \managed_cached\corerun.exe 104857600 4096 Asynchronous 154,884.8 us 0.47 568 B
Read \native_cached\corerun.exe 104857600 4096 Asynchronous 118,937.8 us 0.36 544 B
Write \main\corerun.exe 104857600 4096 None 172,746.9 us 1.00 464 B
Write \main\corerun.exe 104857600 4096 Asynchronous 458,918.6 us 1.00 4506328 B
Write \managed_cached\corerun.exe 104857600 4096 Asynchronous 208,779.5 us 0.46 792 B
Write \native_cached\corerun.exe 104857600 4096 Asynchronous 170,257.2 us 0.37 768 B

Comment thread src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Windows.cs Outdated
Comment thread src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Windows.cs Outdated

@adamsitnik adamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot please address the feedback

Comment thread src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Windows.cs Outdated
Comment thread src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Windows.cs Outdated
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>

Copilot AI commented Jun 9, 2026

Copy link
Copy Markdown
Contributor Author

@copilot please address the feedback

Implemented in 569ccce. The remaining feedback items are addressed: stack NativeOverlapped plus DangerousAddRef/DangerousRelease guarding in sync-over-async paths.

Copilot AI requested a review from adamsitnik June 9, 2026 12:54
Comment thread src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Windows.cs Outdated
Copilot AI review requested due to automatic review settings June 9, 2026 15:32

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.

Comment thread src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Windows.cs Outdated
Comment thread src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Windows.cs Outdated
Comment thread src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Windows.cs Outdated
Comment thread src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Windows.cs Outdated
Comment thread src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Windows.cs Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-System.IO tenet-performance Performance related issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Don't use callbacks when performing sync IO with async handles

4 participants