[WIP] Observable update refactor #4360
Draft
+67
−6
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.
This PR will take a while to materialize, but I already wanted to start thinking this through.
Refactor how internal events are handled
Motivation
Right now we heavily use Observables to propagate events internally, right up to the GPU memory.
A single scatter plot (with axis to be fair) creates 4403 observables:
Further problems with our observable infrastructure:
invoke_latest
.setproperty!
and make the attribute conversions pull based. This should also work quite easily for GLMakie, since it will pull the updates from it's own event thread/task, which doesn't care about where the update came from.Proposal
Get rid of all observables in
Plot
instead have two Dicts and a Set of changed fields:
Now, when accessing any of these in the backend, we will go through all
changed_fields
and run anyconvert_arguments
/convert_attributes
, that relies on that value and will write all values tocomputed_attributes
.isempty(changed_fields)
can also be used as an unexpensive check for GLMakie's on demand renderloop, and insetproperty!
we could also already tell the parent scene that there are changed plots.We can also still make
setproperty!
directly notify the backend by having an observable/condition triggered insetproperty!
.I would also remove the
args
vskw
thing and make them all attributes, if that doesn't make to many problems.Since we have the mapping from
arg_n
->attribute_name
, it should be possible to make this backward compatible.We will also add
Dict{Symbol, Observable}
to haveplot.attribute
still return an observable for backwards compatibility, but I think we should not rely on this in Makie and the backends itself, so that we don't end up with all attributes always materializing back as observables.Problems
calculated_attributes!
depends on connecting the calculations via observables. This is a mess, but I also am not 100% sure how to do this going forward. Same goes forconvert_arguments
, but I kind of hope without observables the code should actually become easier - but it's still a bit hard to judge.convert_attributes
,convert_arguments
andcalculated_attributes!
that need to run on each update.plot!(... ; other_plot.attributes...)
wouldn't propagate the updates anymore.plot!(recipe_plot, ...; color=recipe_plot.color)
neither. I feel like this needs a cleaner API anyways, but simply forwarding the observables here surely is simple from the users perspective. Instead of the aboveDict{Symbol, Observable}
for backwards compatibility, we could also return something likecolor=AttributeView(other_plot, :color)
, which the plot constructor connects internally to the other plot object (plot.color isa AttributeView
). AttributeView would have the large problem, thaton(f, plot.color)
won't easily work, which must be widely used across the Makie ecosystem.