Closed sinlerdev closed 1 year ago
After thinking a bit more about the "con" of such feature, I think it is avoidable- as instead of relying on a whole new storage for storing constant dependencies, we can already use graph
's ._dependencySet.
In addition, after the tree simplification step is finished, we could mark the whole dependent as constant if all of our dependencies are defined as constant- this means that the overhead that comes with dependency deactivation (that still occurs even when all dependencies are constant!), and tree simplification step as well if the dependency capturing still marks the whole dependent as constant.
After some thinking- I believe this on a conceptual level, is the preferred solution for reducing processing time per-update.
Now, I think it is now sensible to design the API that will be used for accessing that internal mechanism- and I have a few API designs:
Syntax Design 1:
Calc(function(useState, useKey)
return useState/useKey(..., true) -- true means constant
end)
Calc(function(useState, useKey)
return useState/useKey(..., false) -- false means dynamic
end)
Note: This design doesn't offer no "default" value- preserving explicitness.
Syntax Design 2:
Calc(function(_, _, useConstant)
return useConstant(obj)/useConstant(obj, key)
end)
Note: While this approach removes the need for passing another argument, it does need yet another overloaded injector
Syntax Design 3:
Calc(function(useState, useKey)
return useState/useKey(...) -- dependencies are automatically treated as constant
end)
Calc(function(useState, useKey)
return useState/useKey(..., false) -- false means dynamic
end)
Note: This is a more of an iteration than Design 1, as it removes the need for manually defining a dependency as constant, however, this optimization will then act as an implicit one, which is against the entire feature's goal.
I think I am going with the second design now that we merged useState
and useKeyState
into a unified use
injector- it signals explicitness very well and avoid some other weird stuff like default values and such.
will be rejected- has figured out a better solution
This is intended as another solution for #3, which solves the issue by allowing the user to define constant dependencies.
Before starting how are we gonna design Explicit definitions for constant dependencies, let's recap the issue we faced that #3 tried to solve.
Consider this pseudocode:
Before diving into the problem this example illustrates, let's divide its behavior into the following:
Dependency capturing is done every time an update is performed, which means lazy evaluation is performed so that case 2 is supported, however, an issue arises when we want to support case 1.
The issue is with supported case 1, is dependency recapturing is always performed, providing the same result, which means that most of our computational power is mostly wasted in repeated tasks.
Additionally, this can be a problem with case 2, where x and y are falsy all the time. This means that we have a problem with defining constant dependencies
Explicit Constant Dependencies Definitions is an attempt to solve this issue by allowing the user to explicitly define if specific dependencies are constant or not, which vinum can optimize by marking constant dependencies as objects that don't need to be:
At the moment, injector calls are allowed to be called at any point, which that can mean constant dependencies definitions can be ignored by the initial capture. To solve this, we can check if a constant dependency is already injected or not, and if it is not, we can mark it as injected and then do all the subscribing magic, however this can also mean that memory footprint can be increased due to the storing constant dependency references in a different storage. This also means that this feature offers potentially great computational optimization in exchange to an increased memory consumption.
This issue is at the discussion phase, so I ask you to leave all of your feedback here as, at the moment, I have no idea how to approach this issue efficiently, as decreased memory footprint is something I care about as much as decreased computational time.