Why is my @animate loop super slow?

Hi!

I’m trying to understand why is the using the Plots.jl @animate macro slower than plotting and saving many times. I destilled my real case into this hopefully MWE.

I have a function that creates a plot with several heatmaps and a function that creates an animation by changing the timestep to be plotted.

Using currently julia 1.5 RC 1

julia> using Plots, BenchmarkTools; gr();default(fmt=:png)

julia> function letsplot(array,indt)
    p1 = @views heatmap(array[:,:,indt])
    p2 = @views heatmap(array[:,:,indt])
    p3 = @views heatmap(array[:,:,indt])
    p4 = @views heatmap(array[:,:,indt])
    p5 = @views heatmap(array[:,:,indt])
    p6 = @views heatmap(array[:,:,indt])
    plot(p1,p2,p3,p4,p5,p6)
end

julia> function animate_test(array)
    anim = @animate for indt in 1  #Only one timestep
        letsplot(array,indt)
    end
end

If I just call the plotting function I get a plot very rapidly.:

julia> @btime letsplot($rand(500,500,100),1)
  97.810 ms (34932 allocations: 215.63 MiB)

But when wrapping it in an animation, the allocations skyrocket, even if I am only iterating in one number.

julia> @btime animate_test($rand(500,500,100))
  12.632 s (240254552 allocations: 4.57 GiB)

In the real case scenario I am doing 600 timesteps and it takes around 40 minutes in creating the final animation. In this example only going through 1 timestep inside the @animate macro creates a lot of allocations and increases the execution time (by a lot 100 miliseconds vs 12 seconds).

Is there a way to make this process more efficient? I’m thinking that in the real case most of the time is spent in garbage collection.

2 Likes

I will comment here because probably posting on a Saturday afternoon was not the best of ideas.

I don’t have an answer, but if you’re interested in figuring this out for yourself I would suggest running both versions of the code with ProfileView.jl to get a sense of where the code is spending most of its time.

Are you using VSCode? I’ve noticed a crazy slowdown sometimes in VSCode with gr() in Plots.jl when creating animations. But it’s pretty iffy on when it happens, so I haven’t been able to reproduce it reliably enough to file an issue. And it always prints send no error or something when it happens.

Sometimes this helps:

previous_GKSwstype = get(ENV, "GKSwstype", "")
ENV["GKSwstype"] = "100"
... do animation...
ENV["GKSwstype"] = previous_GKSwstype 

As I understand it, ENV["GKSwstype"] = "100" prevents the window from popping open which takes a while and isn’t needed when you’re just saving the results immediately.

2 Likes

Oh cool, thanks. Do you have any idea why this only sometimes happens? I can’t seem to find any rhyme or reason to when I’m going to run into this. It has even happened on the same code run from within the same session before.

No; I’ve seen error messages and slowdowns but I was also using remote-into-WSL VSCode feature so I thought it was related to that. But I think the environmental variable might help even not on WSL because then it doesn’t have to start up the GKS thing which seems slow. But I’m pretty ignorant about how it all works.

1 Like

Thanks! I tried that before posting but I wasn’t very succesful. Somehow benchmarking every part of the function is fast but some of them take very long when used together…

Tried this and saw a longer time, what would the reason be?

Not using VS code but Jupyter. It used to get very sluggish on every plot before I set up the default format to png. I think svg is very heavy for this kind of workflows.