-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Optimize ZIO#provideSomeEnvironment
and FiberRef#locallyWith
#9652
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
Optimize ZIO#provideSomeEnvironment
and FiberRef#locallyWith
#9652
Conversation
@@ -467,54 +467,73 @@ object FiberRef { | |||
self => | |||
type Patch = Patch0 | |||
|
|||
def combine(first: Patch, second: Patch): Patch = | |||
final def combine(first: Patch, second: Patch): Patch = |
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.
What about using a final class here instead of an anonymous one? 🤔
Anonymous classes generates quite ugly stack traces
final class PatchFiber[Value0, Patch0] extends FiberRef[Value0] {
type Patch = Patch0
...
}
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 thought about that too, I'll change it 👍
ZIO.uninterruptibleMask { restore => | ||
restore(zio).exitWith { exit => | ||
val oldValue = oldRefs.getOrNull(self) | ||
if (oldValue == null) fiberState.resetFiberRef(self) |
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 (oldValue == null) fiberState.resetFiberRef(self) | |
if (oldValue eq null) fiberState.resetFiberRef(self) |
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.
oldValue
is not an AnyRef
so we can't use eq
FiberRef.currentEnvironment | ||
.locallyWith(f.asInstanceOf[ZEnvironment[Any] => ZEnvironment[Any]])(self.asInstanceOf[ZIO[Any, E, A]]) |
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 is the casting necessary?
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.
Because FiberRef.currentEnvironment
contains a ZEnvironment[Any]
(which is not very correct I know but it's a package-private val) so we have to cast the function to ZEvironment[Any] => ZEvironment[Any]
for the code to compile
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.
LGTM 🚀
ZIO#provideSomeEnvironment
is one of the methods that can be commonly evaluated (depending on the workflow) since it's used byZIO.scoped
. Currently it requires an invocation ofFiberRef#get
and another ofFiberRef#locally
. We can "optimize" it by usingFiberRef#locallyWith
.However, since
locallyWith
is actually implemented asgetWith
+locally
there isn't much benefit of simply changing it. This PR also optimizeslocallyWith
by making it "unfinal" and overriding its implementation to avoid the additionalFiberRef#getWith
.I also made some other minor optimizations such as making the methods in the anonymous class final (since for some reason the Scala compiler doesn't make anonymous classes final 🙄)