Proposal: Multi-value Signal using bitmaps (bit arrays) #217
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Hi 👋, this is a PoC of #213 😄 (all tests still passing 😅)
Description
The basic idea of this PR is demonstrate how Signals could be improved to keep track of multiple values (up to 32) using 1 single node to reduce memory footprint and possibly improve performance when multiple (related) values are accessed within a
computed
oreffect
.In this PoC, assume a Signal can have - instead of value - properties
signal[0] (alias for signal.value)
tosignal[31]
. Just because numeric properties seem to be accessed faster than string properties (it could have beensignal.value0 .. signal.value31
but it's not relevant).For every
get
, we keep track of the index - in a bit array - of the accessed property:And every
set
operation checks whether the node is watching the property whose value is changed:With this as base, we can create signals that have multiple values (up to 32) and create a lot less nodes if all the accessed properties within a
computed
belong to the same Signal, for example:In this particular example, all properties in both
computed
belong to the same signal, so a single node should be created with bitmap set tofields = (1 << 0) | (1 << 1) | (1 << 2)
(for the first). This means that, for example, ifvalue[0]
changes, then the secondcomputed
won't run even though both use the same signal.Now, the DX is awkward so this PoC doesn't attempt to be a final version but rather to suggest creating an even lower primitive than Signal. A Signal could be an abstraction for this new primitive where it only uses one field
value[0]
.An example for such abstraction is the
reader
function which I included in the code. Which allows creating signals in this manner:( Please check the test cases for
reader
😄 )A Signal could look like:
Of course, this example is just an illustration since better optimizations can be made but I think it conveys the point 😅
But Why?
I want to create a factory which creates classes, sort of like this:
Where
t.String
is a config object which is converted to a property descriptor with getter/setter which would use a signal. However, this consumes a lot of memory and it's (relatively) slow if multiple related properties are accessed within acomputed
.I think this could be improved by using a single Signal to watch multiple related properties (well, up to 32). As in the
reader
PoC example, in one of the tests, you can see that 93 properties can be used with just 3 signals instead of defining 93 signals.My implementation is just a PoC, at its current state I just hope to spawn some discussion around this if it's interesting enough to move forward within preact/signals (Please check the new test cases).
I think this could also be interesting for #4 . I don't think all this logic should belong to
Signal
😅 to be honest, it was just easier to implement it there for a PoC PR.