I am trying to make my Makie GUI run faster and allocate less. I have just upgraded to Julia 1.11.2 and thought it was a good opportunity to use function (@main)
in other words, wrap all my global scope code into a function.
As an interesting observation: just going from Julia 1.10.5 to 1.11.2, I expected allocations to become worse, but it turned out the opposite. One function allocated 3.4 GB in 1.10 to just 736 MB in 1.11, another went from 7.36 GB down to 5.34 GB.
That probably does not sound good to you yet. My issue is likely that I am still using my main mutable struct and other arrays as typed global variables, as an earlier attempt to make one main function resulted in interactivity not working.
My program structure, current and planned:
# currently
using GLMakie, Shapefile, # etc
include("otherfunctions_datatypes.jl")
userdirectory = "/data" # user defined folders
function example(axes,maindata:MyData, myarray::BitVector)
# does sometimes something with globals or observables not explicitly imported into the function
# initialize
global (maindata,output2, etc) = load_data(userdirectory, somesettings)
begin
global somenames = somevalues # etc
selection = Observable(falses(length(maindata.x))) #initialize
inside_timeinterval = Observable(trues(length(maindata.x))) #initialize
inside_area = Observable(trues(length(maindata.x))) #initialize
# set up the plotting figure, axes, buttons, toggles
....
end
@lift(selection[] = $inside_timeinterval .&& $inside_area .&& $somefilter)
# I found this to work, slightly different from the way the manual suggested it
on(selection) do sel
empty(axes)
if animate[] == true
# splitting sel into steps, and then:
for loop that includes calls to scatter( maindata.x[step] etc] )
else
scatter( maindata.x[sel] etc)
end
end
on(zooms) # trigger selection via inside_timeinterval[] = indices, etc
on(clicks)
on(button1)
global (maindata, otherarrays) = load_data(...etc)
# sets other global settings or observables
end
on(toggles) # makes an observable change, but triggers immediate plotting by changing something tiny about the area limits to go into the on(selection)
Plan:
# with @main:
using GLMakie, Shapefile, # etc
include("otherfunctions_datatypes.jl")
function (@main)(ARGS)
userdirectory = "/data" # user defined folders, probably it is a better idea to make the program load a user setting file which can stay the same across program updates.
maindata,output2, etc = load_data(userdirectory, somesettings)
somenames = somevalues # now has to include all global declarations including previously first defined in on(button) blocks
selection = Observable(falses(length(maindata.x))) #initialize
inside_timeinterval = Observable(trues(length(maindata.x))) #initialize
inside_area = Observable(trues(length(maindata.x))) #initialize
# set up the plotting figure, axes, buttons, toggles
....
@lift(selection[] = $inside_timeinterval .&& $inside_area .&& $sfilter)
on(selection) do sel
on(zooms) # trigger selection via inside_timeinterval[] = indices, etc
on(clicks) # trigger selection via inside_timeinterval[] = indices, etc
on(button1)
maindata, otherarrays = load_data(...etc)
# I suppose all the "global" statements can now be removed, but all have to be defined in main function scope before to make them visible outside the on block.
end
on(toggles)
end # main function
function example(axes,maindata:MyData,observable1, etc)
# all globals and observable settings imported explicitly
# to start, issue: main(nothing) in REPL, or julia -t auto thisprogram.jl
Do you agree or have other suggestions?