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

Heuristic memoisation for state objects #305

Open
dphfox opened this issue Jan 27, 2024 · 1 comment
Open

Heuristic memoisation for state objects #305

dphfox opened this issue Jan 27, 2024 · 1 comment
Labels
enhancement New feature or request not ready - blocked Waiting on other work to be done

Comments

@dphfox
Copy link
Owner

dphfox commented Jan 27, 2024

Right now, state objects unconditionally memoise their contents, which can build up memory usage when dealing with a large sea of small state objects dealing with lightweight primitive values. For primitive values which can be easily garbage collected, when generated by a process which is lightweight and fast to run, we should disable caching and similarity checks, so values can quickly flow down hot paths.

@dphfox dphfox added enhancement New feature or request not ready - evaluating Currently gauging feedback labels Jan 27, 2024
@dphfox dphfox added not ready - blocked Waiting on other work to be done and removed not ready - evaluating Currently gauging feedback labels Feb 3, 2024
@xiyler
Copy link

xiyler commented Feb 4, 2024

Since I implemented something similar to this in my library, I would like to believe that my insight is somewhat valuable to this discussion. While the concepts behind my implementation are heavily borrowed from Boatbombers' PR, the implementation is entirely different and is actually semi-generic for all state objects.

I believe there are only three possible cases that conditional memoisation is actually concerned with, which are:

  1. The state object has other types of objects as dependents. It doesn't matter if there is an Observer there as well, as such, it's not safe to release the value.
  2. The state object has only Observers as dependents, as such, it's entirely safe to release the value after the observers' listeners are ran. However, this case is slightly more complicated for Fusion than Vinum since Fusion runs Listeners in new coroutines, which means the question whether it should concern itself with yielding and all of its gotchas is important to answer.
  3. The state object has no dependents at all. While it's tempting to also release the value here, its actually worse for performance when you do such a thing since usually state objects that have no dependent are often read by loops (like RenderStepped). Plus, denying to release the value here somewhat makes the "goal" of the optimization perhaps clearer? As in, this optimization enables Computeds (and Deriveds in my library) to act like "Flow" objects where their main concern is to just "pass" values to Observers.

I believe supporting these three cases actually accounts for all possible scenarios (of course, this is limited by how Fusion will handle the complications that are present because of yielding), and usually eliminates the need for recomputing on reading.

Plus, I also think the "best" place for actually all of this "conditional-value-releasing" stuff is actually in updateAll after all objects have recaptured their dependencies, so when we loop again through the queue, we actually decide based on the new dependents. However, this may not apply to SETS as much as it applies to the algorithm I use for Vinum's updates dispatching.

...and I think that's all what I got. Hope this helps :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request not ready - blocked Waiting on other work to be done
Projects
None yet
Development

No branches or pull requests

2 participants