Skip to content

Optimize Parallel instance in GenSpawnInstances to avoid allocation.#4599

Open
nmichael44 wants to merge 1 commit into
typelevel:series/3.xfrom
nmichael44:optimize-genspawn-parallel
Open

Optimize Parallel instance in GenSpawnInstances to avoid allocation.#4599
nmichael44 wants to merge 1 commit into
typelevel:series/3.xfrom
nmichael44:optimize-genspawn-parallel

Conversation

@nmichael44
Copy link
Copy Markdown
Contributor

@nmichael44 nmichael44 commented May 8, 2026

Motivation

Currently in GenSpawnInstances, the Parallel instance provides .parallel and .sequential as defs that instantiate a new (M ~> F) and new (F ~> M) on every invocation.

Because operations like cats.Parallel.parTraverse invoke P.parallel(ma) and P.sequential(ma) for every item in the collection, this creates a large number of FunctionK object allocations during a traversal, putting unnecessary pressure on the garbage collector.

Changes

This PR eliminates these allocations by applying the Id caching technique (similar to Resource.liftK).

  • Extracts the FunctionK instances into a private object GenSpawnInstances to act as true JVM-wide singletons (rather than trait fields).
  • Uses asInstanceOf to cast the cached Id transformations to the required effect type at the call site.

Impact

Zero-allocation parallel and sequential transformations for all effect types that implement GenSpawn. This reduces the memory footprint and GC overhead on hot paths involving parallel collections processing.

…Caches the and FunctionK instances in a private companion object using an Id cast.
@nmichael44
Copy link
Copy Markdown
Contributor Author

nmichael44 commented May 21, 2026

Hi @durban, maybe you could review this one as well? In the same spirit as another one you did recently. There is also one more just like it right next to this one.

@durban
Copy link
Copy Markdown
Contributor

durban commented May 24, 2026

I'm slightly nervous about the .asInstanceOf being "far away" from what we're casting. (In general, I deem .asInstanceOf a code smell. It is correct here, but not obviously correct. The PR I've merged had the cast in the vicinity of the definition, so it was obvious.)

Have you observed the reduced memory footprint and GC overhead you write about? (I believe we have parTraverse benchmarks, for example.)

@nmichael44
Copy link
Copy Markdown
Contributor Author

@durban I did not observe reduced memory -- I wasn't trying to solve a performance problem. I found these by reading the code of cats effect while trying to understand the framework better. Of all the ones you looked this is the one that could have the most impact since we build a natural transform for each element in the collection. But it's up to you. Maybe if I add some comment above the reference to the constant natural transform that would help convince you?

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