pointfreeco / swift-composable-architecture

A library for building applications in a consistent and understandable way, with composition, testing, and ergonomics in mind.
https://www.pointfree.co/collections/composable-architecture
MIT License
11.91k stars 1.37k forks source link

Stack overflow crash on physical device #3146

Closed mishashemin closed 1 month ago

mishashemin commented 1 month ago

Description

Hi! I want to inform you about a known problem with handling large states. On our project in a production environment, we encountered a constant crash during the processing of one of the root state.

The problem is similar to the one in this discussion - https://github.com/pointfreeco/swift-composable-architecture/discussions/3063

At the moment, we have solved the problem with a patch using the ObservedBox from https://github.com/pointfreeco/swift-composable-architecture/discussions/3063

Could you take this into account and make a native decision?

Checklist

Expected behavior

Have a native solution for reducers with large states&

Actual behavior

Stack overflow when using large reducers. Lack of documentation on how to fix the problem

Steps to reproduce

Described in the (https://github.com/pointfreeco/swift-composable-architecture/discussions/3063) discussion

The Composable Architecture version information

1.10.4

Destination operating system

IOS 17.5

Xcode version information

15.4

Swift Compiler version information

swift-driver version: 1.90.11.1 Apple Swift version 5.10 (swiftlang-5.10.0.13 clang-1500.3.9.4)
Target: arm64-apple-macosx14.0
mbrandonw commented 1 month ago

Hi @mishashemin, can you explain your situation more? Just how big is "big" for your state? Are you using our navigation tools for holding onto child state, such as @Presents and StackState? Those tools insert a heap allocated wrapper for you, and we have found that avoids most stack overflow problems.

The discussion you linked to is seemingly a situation where 25 child features are held in a state, and all our non-optional. That seems a little excessive, and probably not a pattern one wants to follow in practice. It doesn't seem common for an app to literally need to hold the state of every feature all at once. More often a child feature is gated by an optional (or array) so that it can represent being "inactive".

We personally do not feel this is an issue with the library. People run into this issue even when not using TCA. The core Swift team has said multiple times that they would like to provide tools to help with this (such as "indirect" struct fields), or even have stack allowed values automatically become heap allocated when necessary. So ideally a general Swift solution would be provided someday.

Since this isn't an issue with the library I am going to convert it to a discussion. Please feel free to continue the conversation over there!