Skip to content

[Internals] Optimise ZStream - Add readInput/readInputUnit and succeedChannelFn to ZChannel#10577

Open
guizmaii wants to merge 47 commits into
zio:series/2.xfrom
guizmaii:perf/shared-zchannel-done-handler
Open

[Internals] Optimise ZStream - Add readInput/readInputUnit and succeedChannelFn to ZChannel#10577
guizmaii wants to merge 47 commits into
zio:series/2.xfrom
guizmaii:perf/shared-zchannel-done-handler

Conversation

@guizmaii

@guizmaii guizmaii commented Mar 13, 2026

Copy link
Copy Markdown
Member

Summary

Reduces boilerplate and avoids Fold.K allocation for the most common readWithCause pattern across ZStream, ZPipeline, ZSink, and ZChannel.

1. succeedChannelFn

Adds succeedChannelFn[Z] shared constant to ZChannel, following the existing unitChannelFn pattern. Returns a pre-cached val via asInstanceOf — one object instead of a per-call-site singleton.

2. readInput / readInputUnit

Two private[zio] convenience methods that replace the most common readWithCause boilerplate — reading input, refailing on error, with a standard done handler. Both use a pre-cached Fold.K instance, avoiding the per-call new Fold.K(...) allocation.

  • readInput — passes through the done value (succeedChannelFn). Used by ZChannel internal combinators (collect, contramap, drain, mapOut, etc.).
  • readInputUnit — discards the done value (unitChannelFn, returns Unit). Zero allocation on done since ZChannel.unit is pre-cached. Used by ZStream/ZPipeline sites.
// Before
ZChannel.readWithCause(
  (in: Chunk[A]) => { ... },
  ZChannel.refailCause,
  (_: Any) => ZChannel.unit,
)

// After
ZChannel.readInputUnit { (in: Chunk[A]) =>
  ...
}

Test plan

  • streamsJVM/compile passes
  • All 1136 streamsTestsJVM tests pass (0 failures)

@CLAassistant

CLAassistant commented Mar 13, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@guizmaii guizmaii self-assigned this Mar 13, 2026
@guizmaii guizmaii marked this pull request as draft March 13, 2026 06:24
Add `refailCauseChannelFn` and `succeedChannelFn` shared constants
in the `ZChannel` companion object, following the existing
`unitChannelFn` pattern. This eliminates per-call-site lambda
allocations for identity error and done handlers across `ZStream`,
`ZPipeline`, `ZSink`, and related files.

- `refailCauseChannelFn[E]` replaces `err => ZChannel.refailCause(err)` and bare `ZChannel.refailCause` eta-expansions
- `succeedChannelFn[Z]` replaces `done => ZChannel.succeedNow(done)` and `ZChannel.succeed(_)` identity pass-throughs
Introduce `readInput` as a specialized `readWithCause` that only takes
the `in` handler, defaulting error to `refailCause` and done to `unit`.
A pre-cached `ReadInputFoldK` avoids allocating a new `Fold.K` on every
call site.

Replace 18 matching `readWithCause(..., refailCauseChannelFn, unitChannelFn)`
call sites across `ZStream`, `ZPipeline`, and `ZSink` with the new
`readInput` method.
…h` semantics

- Rename `readInput` → `readInputCause` and change its done handler from
  `unitChannelFn` (discard) to `succeedChannelFn` (pass-through), making
  the method more general.
- Add new `readInput` that uses `readWith` semantics (fail on errors,
  pass-through done value). Since `readWith(in, fail(_), done)` is
  semantically equivalent to `readWithCause(in, refailCause, done)`,
  it delegates to `readInputCause` — no separate `Fold.K` needed.
- Replace all applicable `readWithCause(..., refailCauseChannelFn, succeedChannelFn)`
  and `readWith(..., fail(_), succeedChannelFn)` call sites across
  `ZChannel`, `ZStream`, `ZPipeline`, and `ZSink`.
- Sites with `ZNothing` as `InErr` are left as `readWithCause` due to
  Scala 2 type inference limitations.
@guizmaii guizmaii force-pushed the perf/shared-zchannel-done-handler branch from 1671975 to 637eb33 Compare March 13, 2026 07:26
@guizmaii guizmaii changed the title Deduplicate ZChannel done-handler lambdas into shared constants Deduplicate ZChannel handler lambdas and add readInput/readInputCause Mar 13, 2026
`readInputCause` uses `succeedChannelFn` which allocates a
`SucceedNow(done)` when the upstream completes. For sites that
discard the done value (all `ZStream`/`ZPipeline` usages),
`readInputCauseUnit` uses the pre-cached `unitChannelFn` instead.
The shared constant provided no meaningful optimization: the JVM
already caches eta-expanded method references per call site, and the
real allocation (`Fail(() => cause)`) happens on invocation regardless.

Also adds `readInputCauseUnit` which uses `unitChannelFn` (pre-cached
`ZChannel.unit` singleton) instead of `succeedChannelFn` (allocates
`SucceedNow(done)`). All `ZStream`/`ZPipeline` sites now use
`readInputCauseUnit` since they discard the done value.
@guizmaii guizmaii changed the title Deduplicate ZChannel handler lambdas and add readInput/readInputCause Deduplicate \ZChannel\ handler lambdas and add \readInputCause\/\readInputCauseUnit\ Mar 13, 2026
@guizmaii guizmaii force-pushed the perf/shared-zchannel-done-handler branch from 44ee434 to a9b86c8 Compare March 13, 2026 08:13
`readInputCauseUnit` now correctly returns `ZChannel[..., Unit]`
instead of `Any`, matching the `unitChannelFn` done handler.
Also inlines `refailCause` directly in `Fold.K` constructors.
@guizmaii guizmaii changed the title Deduplicate \ZChannel\ handler lambdas and add \readInputCause\/\readInputCauseUnit\ Add readInputCause/readInputCauseUnit and succeedChannelFn to ZChannel Mar 13, 2026
@guizmaii guizmaii force-pushed the perf/shared-zchannel-done-handler branch from 5eb5d1f to 9cd8f7b Compare March 13, 2026 08:51
@guizmaii guizmaii requested review from hearnadam and kyri-petrou and removed request for hearnadam March 13, 2026 09:31
@guizmaii guizmaii marked this pull request as ready for review March 13, 2026 09:31
@guizmaii guizmaii changed the title Add readInputCause/readInputCauseUnit and succeedChannelFn to ZChannel [Internal] Add readInputCause/readInputCauseUnit and succeedChannelFn to ZChannel Mar 13, 2026
@guizmaii guizmaii changed the title [Internal] Add readInputCause/readInputCauseUnit and succeedChannelFn to ZChannel [Internals] Add readInputCause/readInputCauseUnit and succeedChannelFn to ZChannel Mar 13, 2026
@guizmaii guizmaii changed the title [Internals] Add readInputCause/readInputCauseUnit and succeedChannelFn to ZChannel [Internals] Optimise ZStream - Add readInputCause/readInputCauseUnit and succeedChannelFn to ZChannel Mar 13, 2026
@guizmaii guizmaii changed the title [Internals] Optimise ZStream - Add readInputCause/readInputCauseUnit and succeedChannelFn to ZChannel [Internals] Optimise ZStream - Add readInput/readInputUnit and succeedChannelFn to ZChannel Mar 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants