# Memory allocation within loop

**URL:** <https://discourse.julialang.org/t/memory-allocation-within-loop/23999>\
**Category:** Performance\
**Tags:** question\
**Created:** [May 8, 2019, 3:13pm UTC](https://discourse.julialang.org/t/memory-allocation-within-loop/23999 "2019-05-08T15:13:53Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![drarnau](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/drarnau/32/4476_2.png) [@drarnau](https://discourse.julialang.org/u/drarnau)\
**Post date:** [May 8, 2019, 3:13pm UTC](https://discourse.julialang.org/t/memory-allocation-within-loop/23999/1 "2019-05-08T15:13:53Z")

</div>

I have a `for` loop in which I create a function that I optimize, something like:

```julia
using Interpolations, Optim
function PolicyFunction()
    V = Array{Float64}(undef, 201, 40)
    n = Array{Float64}(undef, 201, 40)

    grid_h = range(10.0, stop = 300, length = 201)

    for j = 40:-1:1
        if j == 40 # Last period
            nextV = zeros(201)
        else
            nextV = V[:,j+1]
        end

        # Linerar interpolation for this period
        MyItp = interpolate((grid_h,), nextV, Gridded(Linear()))
        V_tw = extrapolate(MyItp, Line())
        for (ind_h, h) in enumerate(grid_h)
            # Define aux function to maximise
            aux_f(n_td) = log(1-n_td) + (0.95*V_tw(n_td^2.0))
            result = optimize(aux_f, 0.01, 0.99, GoldenSection())

            Optim.converged(result) || error("Failed to converge")
            n[ind_h, j] = Optim.minimizer(result)
            V[ind_h, j] = Optim.minimum(result)
        end
    end
    return n
end

```

With this implementation I get:

```julia
@time PolicyFunction()
  0.106507 seconds (1.68 M allocations: 32.176 MiB, 3.05% gc time)

```

I’m happy with the time but I was surprised with the memory allocation (in my real application I get something like `148.13 M allocations: 2.238 GiB, 2.08% gc time`. When I use a more rudimentary solution like:

```julia
function PolicyFunction()
    V = Array{Float64}(undef, 201, 40)
    n = Array{Float64}(undef, 201, 40)

    grid_h = range(10.0, stop = 300, length = 201)

    for j = 40:-1:1
        # Define vector for next period
        if j == 40 # Last period
            nextV = zeros(201)
        else
            nextV = V[:,j+1]
        end

        # Linerar interpolation for this period
        MyItp = interpolate((grid_h,), nextV, Gridded(Linear()))
        V_tw = extrapolate(MyItp, Line())

        for (ind_h, h) in enumerate(grid_h)
            V_max = - Inf
            for n_td in range(0.01, stop = 0.99, length = 201)
                V_td = log(1-n_td) + (0.95*V_tw(n_td^2.0))

                if V_td > V_max
                    V_max = V_td
                    n[ind_h, j] = n_td
                    V[ind_h, j] = V_td
                end
            end
        end
    end
    return n
end

```

The time increases (of course depends on the grid points for `n_td`) but the use of memory is much lower (in my real application the difference is even more dramatic):

```julia
0.195065 seconds (150.49 k allocations: 7.371 MiB, 1.22% gc time)

```

Can anybody explain why is there such a difference in memory allocation? Is it because I create a function in each iteration? Is there a way around it?

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [May 8, 2019, 3:17pm UTC](https://discourse.julialang.org/t/memory-allocation-within-loop/23999/2 "2019-05-08T15:17:05Z")

</div>

> [@drarnau](#):
>
> `optimize`

Optim probably allocates some work buffers in `optimize`.

> [@drarnau](#):
>
> I’m happy with the time but I was surprised with the memory allocation (in my real application I get something like `148.13 M allocations: 2.238 GiB, 2.08% gc time` .

If you are happy with the time, do you really care about how many allocations that occurred?

---

<div class="post-metadata">

**Author:** ![drarnau](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/drarnau/32/4476_2.png) [@drarnau](https://discourse.julialang.org/u/drarnau)\
**Post date:** [May 8, 2019, 3:24pm UTC](https://discourse.julialang.org/t/memory-allocation-within-loop/23999/3 "2019-05-08T15:24:55Z")

</div>

I get similar performance when I use my own implementation of the golden section.

I was thinking that this _high_ use of memory might mask a problem somewhere or inefficient coding…

Edit: This function is part of a bigger iteration and ends up being called _many_ times.

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [May 8, 2019, 3:27pm UTC](https://discourse.julialang.org/t/memory-allocation-within-loop/23999/4 "2019-05-08T15:27:58Z")

</div>

> [@drarnau](#):
>
> I was thinking that this _high_ use of memory might mask a problem somewhere or inefficient coding…

Yeah, that is sometimes the case. The only way to really know is to do some profiling and try to see where time is spent. And then you could try optimize that and see if reducing allocations help with performance.

---

<div class="post-metadata">

**Author:** ![drarnau](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/drarnau/32/4476_2.png) [@drarnau](https://discourse.julialang.org/u/drarnau)\
**Post date:** [May 8, 2019, 3:34pm UTC](https://discourse.julialang.org/t/memory-allocation-within-loop/23999/5 "2019-05-08T15:34:38Z")

</div>

Any tutorial on how to do profiling?

Thanks!

---

<div class="post-metadata">

**Author:** ![stillyslalom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stillyslalom/32/45687_2.png) [@stillyslalom](https://discourse.julialang.org/u/stillyslalom)\
**Post date:** [May 8, 2019, 5:08pm UTC](https://discourse.julialang.org/t/memory-allocation-within-loop/23999/6 "2019-05-08T17:08:03Z")

</div>

There are a few profiling options, depending on your feelings about GUIs. Julia’s built-in profiling tools will print a text-based function call tree annotated with the number of times each function was called:

```julia
using Profile
Profile.clear()
@profile PolicyFunction()
Profile.print()

```

[ProfileView](https://github.com/timholy/ProfileView.jl) gives you a graphical view of the tree, and Juno’s built-in [@profiler](http://docs.junolab.org/latest/man/juno_frontend/#Profiler-1) macro (my preferred method) gives a view of the tree as well as a histogram of call frequency overlaid on the lines of your script.

---

<div class="post-metadata">

**Author:** ![tbeason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tbeason/32/15898_2.png) [@tbeason](https://discourse.julialang.org/u/tbeason)\
**Post date:** [May 8, 2019, 5:43pm UTC](https://discourse.julialang.org/t/memory-allocation-within-loop/23999/7 "2019-05-08T17:43:40Z")

</div>

Optim creates a new ResultSet for every optimization that you do, it does not reuse it. This leads to large memory allocations when your optimization is in your inner loop like this.

However! From what I remember, I did hack together my own univariate optimizer exactly modeled off the one in the package but that didn’t create structs for every run. Memory allocations decreased, but the performance was really not much different (again, just my recollection). I think they just get garbage collected fairly efficiently or something.

---

<div class="post-metadata">

**Author:** ![asyadav](https://avatars.discourse-cdn.com/v4/letter/a/3be4f8/32.png) [@asyadav](https://discourse.julialang.org/u/asyadav)\
**Post date:** [June 28, 2020, 2:17am UTC](https://discourse.julialang.org/t/memory-allocation-within-loop/23999/8 "2020-06-28T02:17:32Z")

</div>

Hi @drarnau, I’m also trying to code up a lifecycle model in Julia, which looks very similar to the example you posted. Did you end up finding a way to reduce allocations/speed up the optimization?
