From ba4d9806c84934d43bc2de9cc1713542444aed5c Mon Sep 17 00:00:00 2001 From: kyri-petrou <67301607+kyri-petrou@users.noreply.github.com> Date: Mon, 16 Jun 2025 08:18:06 +0300 Subject: [PATCH 1/2] Optimize error path in FiberRuntime --- .../scala/zio/internal/FiberRuntime.scala | 45 +++++++++++++------ .../zio/internal/StackTraceBuilder.scala | 15 +++---- 2 files changed, 38 insertions(+), 22 deletions(-) diff --git a/core/shared/src/main/scala/zio/internal/FiberRuntime.scala b/core/shared/src/main/scala/zio/internal/FiberRuntime.scala index d741c3776ef9..d12a48eaab0e 100644 --- a/core/shared/src/main/scala/zio/internal/FiberRuntime.scala +++ b/core/shared/src/main/scala/zio/internal/FiberRuntime.scala @@ -538,7 +538,9 @@ final class FiberRuntime[E, A](fiberId: FiberId.Runtime, fiberRefs0: FiberRefs, val stack = _stack val size = _stackSize // racy - builder += _lastTrace + var last = _lastTrace + builder += last + try { if (stack ne null) { var i = (if (stack.length < size) stack.length else size) - 1 @@ -546,13 +548,19 @@ final class FiberRuntime[E, A](fiberId: FiberId.Runtime, fiberRefs0: FiberRefs, while (i >= 0) { val k = stack(i) if (k ne null) { // racy - builder += k.trace + val trace = k.trace + if (trace ne last) { + last = trace + builder += trace + } i -= 1 } } } - builder += id.location // TODO: Allow parent traces? + val loc = id.location + if (loc ne last) + builder += id.location // TODO: Allow parent traces? StackTrace(self.fiberId, builder.result()) } finally { @@ -844,19 +852,27 @@ final class FiberRuntime[E, A](fiberId: FiberId.Runtime, fiberRefs0: FiberRefs, * * '''NOTE''': This method must be invoked by the fiber itself. */ - private def patchRuntimeFlags[R, E, A]( + private def patchRuntimeFlags[R, E0, A0]( + patch: RuntimeFlags.Patch, + cause: Cause[E0], + continueEffect: ZIO[R, E0, A0] + ): ZIO[R, E0, A0] = + patchRuntimeFlagsCause(patch, cause) match { + case null => continueEffect + case c => Exit.Failure(c) + } + + private def patchRuntimeFlagsCause[E0]( patch: RuntimeFlags.Patch, - cause: Cause[E], - continueEffect: ZIO[R, E, A] - ): ZIO[R, E, A] = { + cause: Cause[E0] + ): Cause[E0] = { val changed = patchRuntimeFlagsOnly(patch) val interruptEnabled = RuntimeFlags.Patch.isEnabled(patch, RuntimeFlag.Interruption.mask) if (changed && interruptEnabled && shouldInterrupt()) { - if (cause ne null) Exit.Failure(cause ++ getInterruptedCause()) - else Exit.Failure(getInterruptedCause()) - } else if (cause ne null) Exit.Failure(cause) - else continueEffect + if (cause ne null) cause ++ getInterruptedCause() + else getInterruptedCause() + } else cause } /** @@ -1241,12 +1257,15 @@ final class FiberRuntime[E, A](fiberId: FiberId.Runtime, fiberRefs0: FiberRefs, } case updateFlags: ZIO.UpdateRuntimeFlags => - cur = patchRuntimeFlags(updateFlags.update, cause, null) + cause = patchRuntimeFlagsCause(updateFlags.update, cause) } } if (cur eq null) { - return failure + val f = + if (cause eq failure.cause) failure + else Exit.Failure(cause) + return f } case updateRuntimeFlags: UpdateRuntimeFlags => diff --git a/core/shared/src/main/scala/zio/internal/StackTraceBuilder.scala b/core/shared/src/main/scala/zio/internal/StackTraceBuilder.scala index df0dc3ac6bc1..2cf43c2e617a 100644 --- a/core/shared/src/main/scala/zio/internal/StackTraceBuilder.scala +++ b/core/shared/src/main/scala/zio/internal/StackTraceBuilder.scala @@ -22,19 +22,16 @@ import scala.collection.mutable.ArrayBuilder import scala.reflect.ClassTag private[zio] class StackTraceBuilder private () { self => - private var last: Trace = null.asInstanceOf[Trace] - private val builder = new ArrayBuilder.ofRef()(ClassTag.AnyRef.asInstanceOf[ClassTag[Trace]]) + private[this] val builder = new ArrayBuilder.ofRef()(ClassTag.AnyRef.asInstanceOf[ClassTag[Trace]]) - def +=(trace: Trace): Unit = - if ((trace ne null) && (trace ne Trace.empty) && (trace ne last)) { + def +=(trace: Trace): Unit = { + if ((trace ne null) && (trace ne Trace.empty)) builder += trace - last = trace - } + () + } - def clear(): Unit = { + def clear(): Unit = builder.clear() - last = null.asInstanceOf[Trace] - } def result(): Chunk[Trace] = Chunk.fromArray(builder.result()) From 01aaafe269a65eff39b8b43a08e1fa0207f07905 Mon Sep 17 00:00:00 2001 From: kyri-petrou <67301607+kyri-petrou@users.noreply.github.com> Date: Wed, 18 Jun 2025 20:00:46 +0300 Subject: [PATCH 2/2] PR comments --- .../shared/src/main/scala/zio/internal/FiberRuntime.scala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/shared/src/main/scala/zio/internal/FiberRuntime.scala b/core/shared/src/main/scala/zio/internal/FiberRuntime.scala index d12a48eaab0e..c93fc732347c 100644 --- a/core/shared/src/main/scala/zio/internal/FiberRuntime.scala +++ b/core/shared/src/main/scala/zio/internal/FiberRuntime.scala @@ -560,7 +560,7 @@ final class FiberRuntime[E, A](fiberId: FiberId.Runtime, fiberRefs0: FiberRefs, val loc = id.location if (loc ne last) - builder += id.location // TODO: Allow parent traces? + builder += loc // TODO: Allow parent traces? StackTrace(self.fiberId, builder.result()) } finally { @@ -852,11 +852,11 @@ final class FiberRuntime[E, A](fiberId: FiberId.Runtime, fiberRefs0: FiberRefs, * * '''NOTE''': This method must be invoked by the fiber itself. */ - private def patchRuntimeFlags[R, E0, A0]( + private def patchRuntimeFlags[E0, A0]( patch: RuntimeFlags.Patch, cause: Cause[E0], - continueEffect: ZIO[R, E0, A0] - ): ZIO[R, E0, A0] = + continueEffect: Exit[E0, A0] + ): Exit[E0, A0] = patchRuntimeFlagsCause(patch, cause) match { case null => continueEffect case c => Exit.Failure(c)