-
Couldn't load subscription status.
- Fork 1.4k
Optimisation - FiberRuntime: bypass evaluation of flatmap.first when possible
#9393
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
Conversation
1f5f1ad to
6b6d565
Compare
flatmap.first and fold.first when possibleflatmap.first and fold.first when possible
flatmap.first and fold.first when possibleflatmap.first and fold.first when possible
303c192 to
06ea1f0
Compare
β¦ `fold.first` when possible
06ea1f0 to
96acda6
Compare
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.
Some minor comments, but I think this shortcut makes a lot of sense since we have a lot of ZIO methods that return Unit and we compose them in for-comprehensions or using *>. Avoiding the additional method invocation and pushing/popping from the stack should make things noticeably faster for some programs, so thank you π
| else if (first.isInstanceOf[Success[Any]]) cur = flatmap.successK(first.asInstanceOf[Success[Any]].value) | ||
| else if (first.isInstanceOf[Failure[Any]]) cur = first |
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.
I think let's remove these 2 branches. Exit overrides flatMap so unless we construct one somewhere manually with an exit as first then it won't exist. To double-check this I run the ZIO tests with the line below and it wasn't printed at all
if (flatmap.first.isInstanceOf[Success[Any]]) println("flatmap.first is Success")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.
Done
| case failure => | ||
| cur = failure | ||
| if (null eq result) return null | ||
| else { |
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.
While we're at it, let's remove this else statement. It doesn't make sense since return will exit the method anyways
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.
Done
| if (first eq ZIO.unit) cur = fold.successK(()) | ||
| else if (first.isInstanceOf[Success[Any]]) cur = fold.successK(first.asInstanceOf[Success[Any]].value) | ||
| else if (first.isInstanceOf[Failure[Any]]) cur = exitFailure(first.asInstanceOf[Failure[Any]].cause) |
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.
I think let's keep Fold as is to make it easier on the C2 compiler to optimize the branches. I run the ZIO test suite using if (fold.first eq ZIO.unit) println("fold.first is ZIO.unit") and it was printed 50 times only, so perhaps the shortcut here might end up making things worse overall
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.
I run the ZIO test suite using if (fold.first eq ZIO.unit) println("fold.first is ZIO.unit") and it was printed 50 times only, so perhaps the shortcut here might end up making things worse overall
Don't you think this might happen more often in a real codebase? π€
If it's happening 50 times just in the unit tests, I'd expect it more in an actual code, no?
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.
If it's happening 50 times just in the unit tests, I'd expect it more in an actual code, no?
I find it a bit hard to believe. There are 2,500 tests (plus nonFlaky annotations) plus the test executor code etc. A single test can contain hundreds/thousands of invocations of the runloop. I find it a bit hard to believe that user code will somehow result in having lots of cases where the this branch would be invoked
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.
Fair enough. I made the change
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.
| @inline def exitFailure(cause: Cause[Any]): ZIO.Erased = | ||
| if (shouldInterrupt()) Exit.Failure(cause.stripFailures) else fold.failureK(cause) |
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.
This comment is redundant because I think we'll end up removing this code, but as a side-note, the @inline annotation doesn't work for Scala 3. So for performance-critical code paths we either shouldn't be using it or we should make it Scala-version specific
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.
Removed
4676d13 to
23e273a
Compare
flatmap.first and fold.first when possibleflatmap.first when possible
| case f: Failure[Any] => | ||
| val cause = f.cause | ||
| if (shouldInterrupt()) cur = Exit.Failure(cause.stripFailures) |
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.
Why do we need to strip the failure at all?
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.
No idea. That's a good question π
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.
Thanks again π
I'd like your opinion on these changes. The goal is to try to reduce the number of recursive calls
It'd, for example, benefit this change: #9388