# Understanding allocations in GeometryBasics.jl

**URL:** <https://discourse.julialang.org/t/understanding-allocations-in-geometrybasics-jl/71252>\
**Category:** Performance\
**Created:** [November 10, 2021, 10:42am UTC](https://discourse.julialang.org/t/understanding-allocations-in-geometrybasics-jl/71252 "2021-11-10T10:42:31Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![peremato](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/peremato/32/29128_2.png) [@peremato](https://discourse.julialang.org/u/peremato)\
**Post date:** [November 10, 2021, 10:42am UTC](https://discourse.julialang.org/t/understanding-allocations-in-geometrybasics-jl/71252/1 "2021-11-10T10:42:31Z")

</div>

I am currently using GeometryBasics.jl for a project. While optimizing the code, I noticed lots of memory allocations that hinders performance. Some of them I could figure it out but this one I cannot. Can somebody help me understanding why in the following test code there is one allocation. The code is really trivial and I was expecting no allocation. I am using version 1.6.2.

```julia
julia> using GeometryBasics, BenchmarkTools

julia> function tt2(p::Point3)
           p[1]*p[1] + p[2]*p[2] + p[3]*p[3]
       end
tt2 (generic function with 1 method)

julia> a = Point3{Float64}(1,1,1)
3-element Point3{Float64} with indices SOneTo(3):
 1.0
 1.0
 1.0

julia> @btime tt2(a)
  20.325 ns (1 allocation: 16 bytes)
3.0

```

Thanks,

Pere

---

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [November 10, 2021, 11:13am UTC](https://discourse.julialang.org/t/understanding-allocations-in-geometrybasics-jl/71252/2 "2021-11-10T11:13:56Z")

</div>

Interpolate your variables into benchmark tools macros, with `$`:

```julia
@btime tt2($a)

```

Your `tta` funciton is just math on `Float64` - there’s nothing to allocate. So it’s the global variable that is causing those allocations. Interpolating the variable moves it to the scope of the benchmark.

---

<div class="post-metadata">

**Author:** ![peremato](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/peremato/32/29128_2.png) [@peremato](https://discourse.julialang.org/u/peremato)\
**Post date:** [November 10, 2021, 11:23am UTC](https://discourse.julialang.org/t/understanding-allocations-in-geometrybasics-jl/71252/3 "2021-11-10T11:23:53Z")

</div>

Thanks. I didn’t know. Is there an equivalent for `@time`?

```julia
julia> @time tt2(a)
  0.000004 seconds (1 allocation: 16 bytes)
3.0

```

---

<div class="post-metadata">

**Author:** ![peremato](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/peremato/32/29128_2.png) [@peremato](https://discourse.julialang.org/u/peremato)\
**Post date:** [November 10, 2021, 1:51pm UTC](https://discourse.julialang.org/t/understanding-allocations-in-geometrybasics-jl/71252/4 "2021-11-10T13:51:21Z")

</div>

Now that I understand that just math functions should not allocate, I found that looping on existing and preallocated data structures does allocate. See the example:

```julia
using GeometryBasics, BenchmarkTools

function mod2(p::Point3)
    p[1]*p[1] + p[2]*p[2] + p[3]*p[3]
end

struct Triangle
    a::Point3
    b::Point3
    c::Point3
end
function mod2(t::Triangle)
    mod2(t.a) + mod2(t.b) + mod2(t.c)
end

struct Polygone
    triangles::Vector{Triangle}
end
function mod2(p::Polygone)
    sum = 0.
    for t in p.triangles
        sum += mod2(t)
    end
    sum
end

a = Point3{Float64}(0,0,0)
b = Point3{Float64}(1,0,0)
c = Point3{Float64}(0,1,0)
d = Point3{Float64}(0,0,1)
p = Polygone([Triangle(a,b,c),Triangle(a,b,d),Triangle(a,c,d), Triangle(b,c,d)])

@btime mod2($p)
  374.458 ns (20 allocations: 320 bytes)
9.0

```

Is there a way to avoid these allocations? Thanks.

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [November 10, 2021, 2:04pm UTC](https://discourse.julialang.org/t/understanding-allocations-in-geometrybasics-jl/71252/5 "2021-11-10T14:04:14Z")

</div>

What happens if you define `Triangle` as

```julia
struct Triangle{T}
    a::Point3{T}
    b::Point3{T}
    c::Point3{T}
end

```

That will make this code type stable.

---

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [November 10, 2021, 2:08pm UTC](https://discourse.julialang.org/t/understanding-allocations-in-geometrybasics-jl/71252/6 "2021-11-10T14:08:42Z")

</div>

If something simple like that is allocating, its usually because your code isn’t type stable. To add to oscars example, also `Polygone` `triangles` field will still have the abstract type `Vector{Triangle}`

Use a type parameter instead of an abstract typed field:

```julia
struct Polygone{T<:Vector{<:Triangle}}
    triangles::T
end

```

Or:

```julia
struct Polygone{T<:Triangle}}
    triangles::Vector{T}
end

```

You can check type stability of your funciton calls with the `@code_warntype` macro.

---

<div class="post-metadata">

**Author:** ![peremato](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/peremato/32/29128_2.png) [@peremato](https://discourse.julialang.org/u/peremato)\
**Post date:** [November 10, 2021, 2:19pm UTC](https://discourse.julialang.org/t/understanding-allocations-in-geometrybasics-jl/71252/7 "2021-11-10T14:19:20Z")

</div>

Thanks very much! Adding the type parameter `T` to `Triangle` and `Polygone` the allocations disappear.

```julia
struct Triangle{T}
    a::Point3{T}
    b::Point3{T}
    c::Point3{T}
end

struct Polygone{T}
    triangles::Vector{Triangle{T}}
end

```
