-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Optimise Semaphore code
#10378
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
base: series/2.x
Are you sure you want to change the base?
Optimise Semaphore code
#10378
Conversation
0f43fa5 to
c8cc851
Compare
| * Returns the number of available permits and the number of tasks currently | ||
| * waiting for permits. | ||
| */ | ||
| def stats(implicit trace: Trace): UIO[Semaphore.Stats] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a new little helper to get both available and awaiting in 1 call
| ref.modify { | ||
| case Left(queue) => | ||
| queue | ||
| .find(_._1 == promise) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The culprit for #10377 was most probably this .find call
Also, we were traversing the queue twice, here and below with the queue.filter
c140db5 to
92f8c86
Compare
| val iterator = queue.iterator | ||
| val others = List.newBuilder[Job] | ||
| others.sizeHint(queue.size - 1) | ||
| var foundJob: Job = null | ||
| while (iterator.hasNext) { | ||
| val next = iterator.next() | ||
| if (next.promise == promise) foundJob = next | ||
| else others += next | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI, I'm working on a second PR to optimise this. This is terrible for performances
Edit: See #10382
ccd1df8 to
6062a30
Compare
ae05da8 to
8585229
Compare
|
It looks like we have a few PRs open for optimizing Semaphore at this stage, and I'd rather get just one of them merged in if it solves this issue + improves the performance of Semaphore as in the issue you linked. I updated #9662 to fix the merge issues, would you be able to publish that branch and test it the same way you did for the changes in this PR and let me know whether it performs better / worse / about the same in terms of allocations? |
Fixes #10377
This PR does not fix the performance problem explained in #9093
To fix this problem, the Semaphore algorithm needs to be completely changed (See #10348)
The goal of this PR is to fix the current implementation, which is catastrophic in terms of memory/allocations when a Semaphore is under heavy load
See https://x.com/guizmaii/status/2011286658822656217?s=20 for real world allocation flamegraph showing the issue
Related PR:
Semaphore: Use an optimised data structure to queue jobs #10382