Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid creating a yield ID counter per async writer #2768

Merged
merged 4 commits into from
Jul 9, 2024

Conversation

glbrntt
Copy link
Contributor

@glbrntt glbrntt commented Jul 5, 2024

Motivation:

The NIOAsyncWriter uses an atomic to generate yield IDs. Each writer has its own atomic. We can save an allocatiuon per writer but using a shared atomic.

Each load then wrapping increment operation with relaxed ordering takes approx 3ns on my machine. For a UInt64 this would take approx 188 years to wrap around if run in a tight loop.

Modification:

  • Share a single yield ID counter for NIOAsyncWriter

Result:

Fewer allocations

@glbrntt glbrntt requested a review from FranzBusch July 5, 2024 10:31
@glbrntt glbrntt added the patch-version-bump-only For PRs that when merged will only cause a bump of the patch version, ie. 1.0.x -> 1.0.(x+1) label Jul 5, 2024
Motivation:

The NIOAsyncWriter uses an atomic to generate yield IDs. Each writer has
its own atomic. We can save an allocatiuon per writer but using a shared
atomic.

Each load then wrapping increment operation with relaxed ordering takes
approx 3ns on my machine. For a UInt64 this would take approx 188 years
to wrap around if run in a tight loop.

Modification:

- Share a single yield ID counter for NIOAsyncWriter

Result:

Fewer allocations
@glbrntt glbrntt force-pushed the shared-yield-id-generator branch from 46ed6c1 to 921a1ad Compare July 5, 2024 10:37
@@ -17,6 +17,9 @@ import DequeModule
import NIOConcurrencyHelpers
import _NIODataStructures

@usableFromInline
let yieldIDCounter = ManagedAtomic<UInt64>(0)
Copy link
Contributor

Choose a reason for hiding this comment

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

This would probably be nicer as a static, but this is otherwise reasonable.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed but wasn't sure where to put it. The obvious place is NIOAsyncWriter but that's generic so can't have a static let.

Copy link
Member

Choose a reason for hiding this comment

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

I am not sure if I agree with this move. I understand that we want to reduce allocations but IMO the correct move forward is to replace SwiftAtomics.ManagedAtomic with Synchronisation.Atomic which should avoid the allocation as well since it is ~Copyable. We ought to be able to do this conditionally when the compiler is Swift 6. Though availability might be tricky. If availability blocks us we can move this into a global. I would suggest renaming though to scope it better e.g. let _asyncWriterYieldIDCounter or something like that

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I agree re: using Synchronization.Atomic but as noted, the availability makes this difficult. I've renamed the global though.

@glbrntt glbrntt enabled auto-merge (squash) July 9, 2024 11:52
@glbrntt glbrntt merged commit abbb144 into apple:main Jul 9, 2024
16 of 17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
patch-version-bump-only For PRs that when merged will only cause a bump of the patch version, ie. 1.0.x -> 1.0.(x+1)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants