# Moving source line moves allocation?

**URL:** <https://discourse.julialang.org/t/moving-source-line-moves-allocation/9613>\
**Category:** New to Julia\
**Created:** [March 9, 2018, 6:19pm UTC](https://discourse.julialang.org/t/moving-source-line-moves-allocation/9613 "2018-03-09T18:19:23Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![Pier](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pier/32/7335_2.png) [@Pier](https://discourse.julialang.org/u/Pier)\
**Post date:** [March 9, 2018, 6:19pm UTC](https://discourse.julialang.org/t/moving-source-line-moves-allocation/9613/1 "2018-03-09T18:19:23Z")

</div>

I am trying to fix allocation issues in a function and I see a behaviour which seems strange to me. What follows are two outputs of julia --track.allocation

```julia
- function g11!(x::Array{Float64},f::SubArray{Float64},heq::SubArray{Float64},hineq::SubArray{Float64})
     432 f[1]=x[1]^2+(x[2]-1.0)^2
       0 heq[1]=x[2]-x[1]^2
       - hineq=nothing
       0 nothing
       - end

```

```julia
- function g11!(x::Array{Float64},f::SubArray{Float64},heq::SubArray{Float64},hineq::SubArray{Float64})
     432 heq[1]=x[2]-x[1]^2
       0 f[1]=x[1]^2+(x[2]-1.0)^2
       - hineq=nothing
       0 nothing
       - end

```

First oddity is that the allocation seems to happen in the first case for f[1] and the second time for heq[1]. Furthermore since f and heq are in fact views of preallocated Arrays I would expect no allocation to take place at all. I am surely missing something, but what?

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [March 9, 2018, 6:24pm UTC](https://discourse.julialang.org/t/moving-source-line-moves-allocation/9613/2 "2018-03-09T18:24:12Z")

</div>

Compilation of a function allocates memory, which will show up in your `.mem` file unless you’re careful. From the [manual](https://docs.julialang.org/en/stable/manual/profile/#Memory-allocation-analysis-1):

> More significantly, JIT-compilation also adds to allocation counts, because much of Julia’s compiler is written in Julia (and compilation usually requires memory allocation). The recommended procedure is to force compilation by executing all the commands you want to analyze, then call Profile.clear\_malloc\_data() to reset all allocation counters. Finally, execute the desired commands and quit Julia to trigger the generation of the .mem files.

And note that you need to do all of that within the same Julia session, so:

```julia
f()
Profile.clear_malloc_data()
f()

```

---

<div class="post-metadata">

**Author:** ![Pier](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pier/32/7335_2.png) [@Pier](https://discourse.julialang.org/u/Pier)\
**Post date:** [March 9, 2018, 7:52pm UTC](https://discourse.julialang.org/t/moving-source-line-moves-allocation/9613/3 "2018-03-09T19:52:54Z")

</div>

The two logs I showed have been obtained exactly as you suggest. What follows is a complete self-contained example.

```julia
function g11!(x::Array{Float64},f::SubArray{Float64},heq::SubArray{Float64},hineq::SubArray{Float64})
    f[1]=x[1]^2+(x[2]-1.0)^2
    heq[1]=x[2]-x[1]^2
    hineq=nothing
    nothing
end

function testfun()
    nind=2
    nobj=1
    neq=1
    nineq=0
    f=Array{Float64}(nobj,nind)
    heq=Array{Float64}(neq,nind)
    hineq=Array{Float64}(nineq,nind)

    for i=1:nind
        x=rand(Float64,2)
        @views g11!(x,f[:,i],heq[:,i],hineq[:,i])
    end

end

testfun()
Profile.clear_malloc_data()
testfun()

```

Looking at the complete example shows another oddity:

```julia
 240 f=Array{Float64}(nobj,nind)
       96 heq=Array{Float64}(neq,nind)

```

why have the two arrays, which have the same number of rows and columns, different allocations?

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [March 9, 2018, 9:08pm UTC](https://discourse.julialang.org/t/moving-source-line-moves-allocation/9613/4 "2018-03-09T21:08:16Z")

</div>

Interesting! Thanks for posting the full example. I wonder if the fact the type of `hineq` changes to Void is relevant?

---

<div class="post-metadata">

**Author:** ![Pier](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pier/32/7335_2.png) [@Pier](https://discourse.julialang.org/u/Pier)\
**Post date:** [March 9, 2018, 9:14pm UTC](https://discourse.julialang.org/t/moving-source-line-moves-allocation/9613/5 "2018-03-09T21:14:34Z")

</div>

No. In the following example I only have f and heq, and the behaviour is the same.

```julia
        - function g11!(x::Array{Float64},f::SubArray{Float64},heq::SubArray{Float64})
      192 f[1]=x[1]^2+(x[2]-1.0)^2
        0 heq[1]=x[2]-x[1]^2
        0 nothing
        - end
        - 
        - function testfun()
        - nind=2
        - nobj=1
        - neq=1
      240 f=Array{Float64}(nobj,nind)
       96 heq=Array{Float64}(neq,nind)
        - 
        0 for i=1:nind
        0 x=rand(Float64,2)
        0 @views g11!(x,f[:,i],heq[:,i])
        - end
        - 
        - end
        - 
        - testfun()
        - Profile.clear_malloc_data()
        - testfun()

```

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [March 9, 2018, 9:28pm UTC](https://discourse.julialang.org/t/moving-source-line-moves-allocation/9613/6 "2018-03-09T21:28:45Z")

</div>

At this point I’m just guessing but…perhaps the allocation of `x=rand(Float64, 2)` in `testfun()` is being misattributed to the first line of `g11!` ?

---

<div class="post-metadata">

**Author:** ![Pier](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pier/32/7335_2.png) [@Pier](https://discourse.julialang.org/u/Pier)\
**Post date:** [March 9, 2018, 9:51pm UTC](https://discourse.julialang.org/t/moving-source-line-moves-allocation/9613/7 "2018-03-09T21:51:56Z")

</div>

I don’t think so, as the next example shows. Now x is allocated out of the loop. Still f and heq have misteriously (for me) different sizes, and the first line of g11! reports an allocation while the second does not, even if I swap the assignment of f and heq in g11!

```julia
        - function g11!(x::Array{Float64},f::SubArray{Float64},heq::SubArray{Float64})
      192 f[1]=x[1]^2+(x[2]-1.0)^2
        0 heq[1]=x[2]-x[1]^2
        0 nothing
        - end
        - 
        - function testfun()
        - nind=2
        - nobj=1
        - neq=1
      240 f=Array{Float64}(nobj,nind)
       96 heq=Array{Float64}(neq,nind)
       96 x=ones(Float64,2)
        0 x[1]=2.0
        0 x[2]=3.0
        0 for i=1:nind
        0 @views g11!(x,f[:,i],heq[:,i])
        - end
        - 
        - end
        - 
        - testfun()
        - Profile.clear_malloc_data()
        - testfun()

```

---

<div class="post-metadata">

**Author:** ![tkoolen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkoolen/32/1603_2.png) [@tkoolen](https://discourse.julialang.org/u/tkoolen)\
**Post date:** [March 9, 2018, 10:05pm UTC](https://discourse.julialang.org/t/moving-source-line-moves-allocation/9613/8 "2018-03-09T22:05:28Z")

</div>

I think in this case `nind`, `nobj`, and `neq` are being optimized out, so the line with `f` is still the ‘first line of the function’, to which some allocations are likely being misattributed.

Edit: yeah, if you add a line `println("bla")` before `f=...`, the number of allocations for `f` becomes 96.

---

<div class="post-metadata">

**Author:** ![Pier](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pier/32/7335_2.png) [@Pier](https://discourse.julialang.org/u/Pier)\
**Post date:** [March 9, 2018, 10:26pm UTC](https://discourse.julialang.org/t/moving-source-line-moves-allocation/9613/9 "2018-03-09T22:26:51Z")

</div>

Yes! You are indeed right. If I allocate something before f, the the sizes of f and heq coincide. And the same happens for the first line of g11!. Can I therefore conclude that --track-allocations wrongly adds the allocation of function pointers/stuff/whatever to the first line of the function instead of assigning it to the function itself?  
Furthermore the following example shows, probably a related problem

```julia
        - function g11!(x::Array{Float64},f::SubArray{Float64},heq::SubArray{Float64})
 19200000 f[1]=x[1]^2+(x[2]-1.0)^2
        0 heq[1]=x[2]-x[1]^2
        0 nothing
        - end
        - 
        - function testfun()
        - nind=2
        - nobj=1
        - neq=1
      240 f=Array{Float64}(nobj,nind)
       96 heq=Array{Float64}(neq,nind)
        0 for k=1:100000
        0 for i=1:nind
        0 x=rand(Float64,2)
        0 @views g11!(x,f[:,i],heq[:,i])
        - end
        - end
        - end
        - 
        - testfun()
        - Profile.clear_malloc_data()
        - testfun()
        - 

```

if g11! is called repeatedly a lot of memory gets allocated for the function call. Is this expected? It seems to be related to using views because if I use standard Arrays no memory is allocated:

```julia
        - function g11!(x::Array{Float64},f::Array{Float64},heq::Array{Float64})
        0 f[1]=x[1]^2+(x[2]-1.0)^2
        0 heq[1]=x[2]-x[1]^2
        0 nothing
        - end
        - 
        - function testfun()
        - nind=2
        - nobj=1
        - neq=1
      240 f=Array{Float64}(nobj)
       96 heq=Array{Float64}(neq)
        0 for k=1:100000
        0 for i=1:nind
        0 x=rand(Float64,2)
        0 g11!(x,f,heq)
        - end
        - end
        - end
        - 
        - testfun()
        - Profile.clear_malloc_data()
        - testfun()

```

(in this example I could of course use arrays but in the real code I must use views)  
Sorry for abusing everybody’s patience and kindness.

---

<div class="post-metadata">

**Author:** ![Pier](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pier/32/7335_2.png) [@Pier](https://discourse.julialang.org/u/Pier)\
**Post date:** [March 10, 2018, 1:06am UTC](https://discourse.julialang.org/t/moving-source-line-moves-allocation/9613/10 "2018-03-10T01:06:42Z")

</div>

In the end I found your UnsafeVectorView modified it to work with SharedArrays (which was my ultimate goal) and now everything is fine, and the allocations are more or less what I would expect. What I also plan to do is to further modify it in such a way that if I repeatedly create new views of the same array (which I do all the time) I do not create a new view but “recycle” the existing one by updating offset and len (ptr does not change). Why such stuff is not intrinsically part of Julia surprises me, since I believe that what you describe as “extremely cheap views within the inner loop of an algorithm” is surely an extremely common feature of many algorithms.

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [March 10, 2018, 2:01am UTC](https://discourse.julialang.org/t/moving-source-line-moves-allocation/9613/11 "2018-03-10T02:01:05Z")

</div>

The performance issues with views are certainly a known pain point, and I believe that much of the recent work on the compiler has been done to help avoid allocations in cases like this. I’m far from an expert on the compiler, though.

I would suggest trying out your code on the latest v0.7 nightlies (without resorting to UnsafeVectorView) as you may see some substantial improvements.

---

<div class="post-metadata">

**Author:** ![Pier](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pier/32/7335_2.png) [@Pier](https://discourse.julialang.org/u/Pier)\
**Post date:** [March 10, 2018, 10:38am UTC](https://discourse.julialang.org/t/moving-source-line-moves-allocation/9613/12 "2018-03-10T10:38:59Z")

</div>

Thanks for the suggestion. I tried it and the .mem files look ok, but if I do a @time the reported allocated memory appears to be the same. It always confused me that if I add up the reported memory allocation in the .mem files it does not coincide with what @time reports. Is this normal?
