Skip to content
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

Coalesce all merged run effects into a single task group. #3615

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

klundberg
Copy link
Contributor

@klundberg klundberg commented Mar 1, 2025

I noticed that if one were to .merge many .run effects, that it would create as many task groups as there were effects in the list of effects (minus 1). I suspected this may use more memory than needed, so I tried coalescing all run effects into a single task group to save on memory usage.

I ran something like the following code on the simulator both with and without my change to test my hypothesis, in an arbitrary reducer:

case someAction:
  var fx: [EffectOf<Self>] = []
  for _ in 1...1000 {
    fx.append(.run { send in try await Task.sleep(for: .seconds(1)) })
  }
  return .merge(fx)

I'm using a lot of tasks here to make the memory usage differences much more obvious in the memory used metrics in xcode's debugging navigator.

When putting that code into a screen in the swiftui case studies app, without my change the app used approximately 43 MB of memory while the tasks were active, and with my change it used 41.5 or so MB of memory while the tasks were active. This shows that there could be some memory savings gained here especially if some effects in a large group of merged effects are long-lived or if one of them never ends.

Two things I can think of that might be concerns here are the order that effects are initiated is different here; since run effects are coalesced together, if theyre mixed with publisher effects they won't initially trigger in the same order as before this change. The second thing is wrapping the some Sequence<Self> in an unchecked sendable to pass it along to the task group may not be safe. We could create an interim array instead if doing so isn't a concern, but for pathological cases like my test case that may take extra time. If there's little or no concern of assuming that any sequence used here could be safely considered sendable though then it may work fine.

If there's any concerns with this change I can address let me know!

@klundberg klundberg force-pushed the coalesce-task-group-tasks branch from f8344eb to ad18a80 Compare March 1, 2025 03:01
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.

1 participant