# Makie: animation becomes slow after redrawing surface about 25 times

**URL:** https://discourse.julialang.org/t/makie-animation-becomes-slow-after-redrawing-surface-about-25-times/45582
**Category:** Performance
**Created:** [August 26, 2020, 5:38pm UTC](https://discourse.julialang.org/t/makie-animation-becomes-slow-after-redrawing-surface-about-25-times/45582 "2020-08-26T17:38:03Z")
**Posts on this page:** 9
**Page:** 1

<div class="post-metadata">

### Author: ![samo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/samo/32/35398_2.png) [@samo](https://discourse.julialang.org/u/samo)
#### Post date: [August 26, 2020, 5:38pm UTC](https://discourse.julialang.org/t/makie-animation-becomes-slow-after-redrawing-surface-about-25-times/45582/1 "2020-08-26T17:38:03Z")

</div>

# Context

I am working on an example of a 3-D visualization of a 2-D glacier flow. Until now the visualization is done for a very small problem (256x256 grid points). Later it should also work for much larger problems.

# Problem

The animation becomes slow after redrawing surface about 25 times. Here is an outline of the visualization strategy chosen (B\_v is the topography, “the mountain”, and H\_v the glacier height for visualization. #(…) denotes omitted code):

First I set up a scene and draw an empty glacier on it (all NaNs)

```julia
#(...) 
B_v .= B
H_v = fill(NaN, nx, ny)
scene = Makie.surface(X, Y, transpose(B_v), colormap = cgrad(:terrain, scale=:exp10))
glacier = Makie.surface!(scene, X, Y, H_v)

```

Then, I use `record` around the time steps of the simulation and do a redraw of the glacier surface at each time step:

```julia
record(scene, "glacierflow.mp4"; framerate = 25) do io
    for it = 1:nt
        H_v .= H
        H_v[H_v.<=0.01] .= NaN
        HB_v .= transpose(B_v.+H_v)
        Makie.surface!(glacier, X, Y, HB_v, colormap=ice_color, shininess=Float32(2^10), transparency=true, shading=true)
        recordframe!(io)
        #(...) 
    end
end

```

The glacier starts beautifully flowing down the mountain, but after about 25 time steps the glacier flow computations become slow - as if it would do constantly some GC invocations or something. Without the visualisation this slow down is of course not observed. All arrays for the computations are preallocated: there is no allocation happening during the simulation.  
When I monitored the memory usage, I saw that it started at about 930 MB before the visulalization and then it increased slowly and at about 25 times steps it had reached about 1 GB. There the memory usage started to oscillate between about 980 MB and 1050 MB.  
Note that during the simulation there was still about 5 GBs free memory.

# Questions

Do you have any advice on how to mitigate this problem? Should I maybe use other Makie functions for this?

Thanks!!

---

<div class="post-metadata">

### Author: ![sdanisch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sdanisch/32/1406_2.png) [@sdanisch](https://discourse.julialang.org/u/sdanisch)
#### Post date: [August 26, 2020, 5:48pm UTC](https://discourse.julialang.org/t/makie-animation-becomes-slow-after-redrawing-surface-about-25-times/45582/2 "2020-08-26T17:48:57Z")

</div>

This is pretty much exactly the same problem as in: [Makie volume animation froze!](https://discourse.julialang.org/t/makie-volume-animation-froze/43707)

---

<div class="post-metadata">

### Author: ![samo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/samo/32/35398_2.png) [@samo](https://discourse.julialang.org/u/samo)
#### Post date: [August 27, 2020, 3:18pm UTC](https://discourse.julialang.org/t/makie-animation-becomes-slow-after-redrawing-surface-about-25-times/45582/3 "2020-08-27T15:18:05Z")

</div>

Thanks @sdanisch! I am glad to hear that it is an already solved issue 🙂  
However, I am completely new to Makie; so could you be a little more specific on what should be changed?

Moreover, could you please explain me the following: to my understanding `Makie.surface!` would do a update of the surface in place without reallocation. If this is not the case, what is the meaning of the `!` in the function name?

---

<div class="post-metadata">

### Author: ![sdanisch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sdanisch/32/1406_2.png) [@sdanisch](https://discourse.julialang.org/u/sdanisch)
#### Post date: [August 27, 2020, 3:31pm UTC](https://discourse.julialang.org/t/makie-animation-becomes-slow-after-redrawing-surface-about-25-times/45582/4 "2020-08-27T15:31:46Z")

</div>

It adds a new plot, just like `push!`

---

<div class="post-metadata">

### Author: ![samo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/samo/32/35398_2.png) [@samo](https://discourse.julialang.org/u/samo)
#### Post date: [August 27, 2020, 3:32pm UTC](https://discourse.julialang.org/t/makie-animation-becomes-slow-after-redrawing-surface-about-25-times/45582/5 "2020-08-27T15:32:47Z")

</div>

@sdanisch so how would you recommend to update the glacier surface within the time loop?

---

<div class="post-metadata">

### Author: ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)
#### Post date: [August 27, 2020, 4:07pm UTC](https://discourse.julialang.org/t/makie-animation-becomes-slow-after-redrawing-surface-about-25-times/45582/6 "2020-08-27T16:07:24Z")

</div>

I think your confusion comes from this line

```julia
glacier = Makie.surface!(scene, X, Y, H_v)

```

The mutating plotting functions like `plot!(scene, ...` return the scene, not the plot object created (bit weird, but that’s how it is).

You are currently adding a new surface to the scene each frame. That’s super slow.

Instead, you need to update an Observable or Node (same thing) that contains the plotted data. This will cause an update of the plot automatically. There are two ways to do that:

Either you create the Node first, plot it, then update it:

```julia
# create the node
data = Node(rand(10, 10))
# plot it
surface(1:10, 1:10, data)
# update it
data[] = rand(10, 10)
# plot updates automatically

```

Or you plot normal data, it gets wrapped in a Node automatically internally, then you update that internal node by accessing it via index notation. In a surface, the height matrix is the third argument, so this should work:

```julia
data = rand(10, 10)
# plot the data
scene = surface(1:10, 1:10, data)
# extract the plot object from the scene (last added plot)
actual_surface_plot = scene[end]
# get the internal node for the height matrix
internal_data_node = actual_surface_plot[3]
# update it
internal_data_node[] = rand(10, 10)
# plot updates automatically

```

So in your record loop, the only thing you need to do is the node update, the rest is automatic.

---

<div class="post-metadata">

### Author: ![samo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/samo/32/35398_2.png) [@samo](https://discourse.julialang.org/u/samo)
#### Post date: [August 28, 2020, 4:50pm UTC](https://discourse.julialang.org/t/makie-animation-becomes-slow-after-redrawing-surface-about-25-times/45582/7 "2020-08-28T16:50:19Z")

</div>

Thanks @jules! You got it 100%. I assumed

```julia
glacier = Makie.surface!(scene, X, Y, H_v)

```

would give back a handle for the surface, not for the scene. So, I applied your first suggestion with Observables and got

```julia
#(...) 
HB_v = fill(NaN, nx, ny)
HB_vn = Node(HB_v)
scene = Makie.surface(0:dx:lx, 0:dy:ly, transpose(B_v), colormap = cgrad(:terrain, scale=:exp10))
Makie.surface!(scene, X, Y, HB_vn, colormap=ice_color, shininess=Float32(2^10), transparency=true, shading=true)

record(scene, "glacierflow.gif"; framerate = 25) do io
    for it = 1:nt
        #(...) 
        HB_v .= transpose(B_v.+H_v)
        HB_vn[] = HB_v
        recordframe!(io)
        #(...) 
    end
end

```

This works, but now, I have still one little doubt: I am not familiar with the syntax `data[]`, i.e. what does that exactly do?

Then, here you see my first little thing done with Makie:

 ![glacierflow](https://global.discourse-cdn.com/julialang/original/3X/6/8/68acd2356593be9b7ab2565c76ec0ac4f13bf5ce.gif)

It’s very cartoon-like 🙂 What is not bad as it is a purely synthetic setup, but I would very much appreciate any ideas to improve it! The colors are certainly something to change…

Thanks!!

---

<div class="post-metadata">

### Author: ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)
#### Post date: [August 28, 2020, 6:40pm UTC](https://discourse.julialang.org/t/makie-animation-becomes-slow-after-redrawing-surface-about-25-times/45582/8 "2020-08-28T18:40:43Z")

</div>

Cool plot! Sad that the glacier just melts away like that 😉

> I am not familiar with the syntax `data[]`

It’s quite simple really, it just looks weird. Square brackets without assignment are special syntax for the function `Base.getindex`, and assignment with square brackets is special syntax for `Base.setindex!`. You can overload those however you please for your own types to give square brackets special meaning.

As it happens, Observables (or Nodes) have those two overloaded, so `getindex` or `observable[]` just returns the wrapped value inside the Observable, and `setindex!` or `observable[] = xyz` sets a new value and additionally calls all listeners of the Observable to “inform” them of the new value.

You can look at the implementation here, it’s very simple [https://github.com/JuliaGizmos/Observables.jl/blob/master/src/Observables.jl#L125-L136](https://github.com/JuliaGizmos/Observables.jl/blob/master/src/Observables.jl#L125-L136)

This is needed because if you have an Observable `observable = Observable(2)` then `observable = 3` would just assign the Integer 3 to that variable name, while you want to change the content of the Observable `observable`. It’s the same mechanism as with `Base.Ref`.

---

<div class="post-metadata">

### Author: ![samo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/samo/32/35398_2.png) [@samo](https://discourse.julialang.org/u/samo)
#### Post date: [September 2, 2020, 10:16am UTC](https://discourse.julialang.org/t/makie-animation-becomes-slow-after-redrawing-surface-about-25-times/45582/9 "2020-09-02T10:16:27Z")

</div>

Thanks @jules for the additional explanations!

> Cool plot! Sad that the glacier just melts away like that ￼

BTW: what you see here is a simple glacier flow simulation using shallow ice equations: it is a simple nonlinear model of glacier flow over topography under the effect of gravity. To reproduce more what you observe in nature, one would need to add of course other things like precipitation, melting etc.

So thanks again, and if you have any suggestions how to make it look nicer I would be very grateful! BTW: [at 22:06 in my JuliaCon 2020 talk](https://youtu.be/vPsfZUqI4_0?t=1326), there is a simulation using the same model on a real topography; but the visualization was not done with Julia. I would like to make it at least as nice as that with Makie 🙂

PS: for some reason, I cannot mark [@jules first reply](https://discourse.julialang.org/t/makie-animation-becomes-slow-after-redrawing-surface-about-25-times/45582/6) as solution. I will retry later…
