# How to avoid the 2 allocations for any struct?

**URL:** <https://discourse.julialang.org/t/how-to-avoid-the-2-allocations-for-any-struct/24590>\
**Category:** New to Julia\
**Created:** [May 24, 2019, 9:50pm UTC](https://discourse.julialang.org/t/how-to-avoid-the-2-allocations-for-any-struct/24590 "2019-05-24T21:50:33Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jean\_Michel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jean_michel/32/8282_2.png) [@Jean\_Michel](https://discourse.julialang.org/u/Jean_Michel)\
**Post date:** [May 24, 2019, 9:50pm UTC](https://discourse.julialang.org/t/how-to-avoid-the-2-allocations-for-any-struct/24590/1 "2019-05-24T21:50:33Z")

</div>

I illustrate my problem with an example. Say I work heavily with small permutations (elements of the  
symmetric group) and want to multiply them as fast as possible.

A permutation of `1:n` is just given by giving the images of the integers `1` to `n` as a `Vector`  
so I could do

```julia
Perm=Vector{Int}
a=[5,4,3,2,1]
b=[2,1,4,3,5]
function mult(a::Perm,b::Perm)
  r=similar(a)
@inbounds for (i,v) in enumerate(a) r[i]=b[v] end
  r
end

```

and this works quite well:

```julia
julia> @btime mult($a,$b)
  31.705 ns (1 allocation: 128 bytes)
5-element Array{Int64,1}:
 5
 3
 4
 1
 2

```

However the problem is that I must write `mult(a,b)`and not `a*b` as I would like, because  
contrary to what I could do in a language like C++, `Perm` is just an alias and not a type by itself,  
thus if I define

`Base.:*(a::Perm,b::Perm)=...`

I am doing an horrible type hijacking (defining multiplication on `Vector{Int}`).

The only thing I know how to do in Julia is define a `struct` with a field:

```julia
struct Perm
  d::Vector{Int}
end

pa=Perm(a)
pb=Perm(b)

```

Now I can overload `*` without problems

```julia
function Base.:*(a::Perm,b::Perm)
  r=similar(a.d)
  @inbounds for (i,v) in enumerate(a.d) r[i]=b.d[v] end
  Perm(r)
end

```

but I am not as efficient: the multiplication does 2 allocations, since Julia allocates the `struct` and  
its field `d` separately:

```julia
julia> @btime $pa*$pb
  38.247 ns (2 allocations: 144 bytes)
Perm([5, 3, 4, 1, 2])

```

So my question is: can I avoid that? What is the best design in Julia?

---

<div class="post-metadata">

**Author:** ![StevenSiew](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevensiew/32/218393_2.png) [@StevenSiew](https://discourse.julialang.org/u/StevenSiew)\
**Post date:** [May 24, 2019, 9:56pm UTC](https://discourse.julialang.org/t/how-to-avoid-the-2-allocations-for-any-struct/24590/2 "2019-05-24T21:56:46Z")

</div>

[quote=“Jean\_Michel, post:1, topic:24590”]  
How to avoid the 2 allocations for any struct?

```julia
Perm=Vector{Int}
a=[5,4,3,2,1]
b=[2,1,4,3,5]
function mult(a::Perm,b::Perm)
  r=similar(a)
  @inbounds for (i,v) in enumerate(a)
    r[i]=b[v]
  end
  r
end

*(a::Perm,b::Perm) = mult(a,b)

```

Single allocation, problem solved.

Sorry, I forgot about the Perm. Perm is a type of Vector{Int}

---

<div class="post-metadata">

**Author:** ![Jean\_Michel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jean_michel/32/8282_2.png) [@Jean\_Michel](https://discourse.julialang.org/u/Jean_Michel)\
**Post date:** [May 24, 2019, 10:00pm UTC](https://discourse.julialang.org/t/how-to-avoid-the-2-allocations-for-any-struct/24590/3 "2019-05-24T22:00:35Z")

</div>

so you are Hijacking the multiplication for Vector{Int} that I said one should avoid

---

<div class="post-metadata">

**Author:** ![StevenSiew](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevensiew/32/218393_2.png) [@StevenSiew](https://discourse.julialang.org/u/StevenSiew)\
**Post date:** [May 24, 2019, 10:05pm UTC](https://discourse.julialang.org/t/how-to-avoid-the-2-allocations-for-any-struct/24590/4 "2019-05-24T22:05:42Z")

</div>

I don’t kow what you mean by hijacking. That’s the way you are suppose to write code in Julia. You have a type and you overload the type for the operator \*

---

<div class="post-metadata">

**Author:** ![Jean\_Michel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jean_michel/32/8282_2.png) [@Jean\_Michel](https://discourse.julialang.org/u/Jean_Michel)\
**Post date:** [May 24, 2019, 10:08pm UTC](https://discourse.julialang.org/t/how-to-avoid-the-2-allocations-for-any-struct/24590/5 "2019-05-24T22:08:35Z")

</div>

In Julia you can write

`Base.:+(a,b)=0`

but you won’t like the consequences. This is what is called hijacking

---

<div class="post-metadata">

**Author:** ![StevenSiew](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevensiew/32/218393_2.png) [@StevenSiew](https://discourse.julialang.org/u/StevenSiew)\
**Post date:** [May 24, 2019, 10:10pm UTC](https://discourse.julialang.org/t/how-to-avoid-the-2-allocations-for-any-struct/24590/6 "2019-05-24T22:10:22Z")

</div>

Here look at my code

```julia
    # Basic arithmetic functions
    +(x::PDFP, y::PDFP) = PDFP_add(x,y)

    -(x::PDFP) = PDFP_isError(x) ? x : PDFP((x.s+1)%2, x.expo, x.m)

    -(x::PDFP, y::PDFP) = PDFP_sub(x,y)

    *(x::PDFP, y::PDFP) = PDFP_mul(x,y)

    /(x::PDFP, y::PDFP) = PDFP_div(x,y)

```

---

<div class="post-metadata">

**Author:** ![StevenSiew](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevensiew/32/218393_2.png) [@StevenSiew](https://discourse.julialang.org/u/StevenSiew)\
**Post date:** [May 24, 2019, 10:12pm UTC](https://discourse.julialang.org/t/how-to-avoid-the-2-allocations-for-any-struct/24590/7 "2019-05-24T22:12:32Z")

</div>

> [@Jean\_Michel](#):
>
> In Julia you can write
> 
> `Base.:+(a,b)=0`
> 
> but you won’t like the consequences. This is what is called hijacking

You should never write code like that. You should ALWAYS define what type variable “a” and what type variable “b” is in your code.

What you have basically written is

```julia
Base.:+(a::Any,b::Any)=0

```

which is terrible code.

---

<div class="post-metadata">

**Author:** ![Jean\_Michel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jean_michel/32/8282_2.png) [@Jean\_Michel](https://discourse.julialang.org/u/Jean_Michel)\
**Post date:** [May 24, 2019, 10:14pm UTC](https://discourse.julialang.org/t/how-to-avoid-the-2-allocations-for-any-struct/24590/8 "2019-05-24T22:14:29Z")

</div>

`Base.:+(a::Float64,b::Float64)=0`  
is also hijacking

---

<div class="post-metadata">

**Author:** ![StevenSiew](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevensiew/32/218393_2.png) [@StevenSiew](https://discourse.julialang.org/u/StevenSiew)\
**Post date:** [May 24, 2019, 10:16pm UTC](https://discourse.julialang.org/t/how-to-avoid-the-2-allocations-for-any-struct/24590/9 "2019-05-24T22:16:44Z")

</div>

> [@Jean\_Michel](#):
>
> Base.:+(a::Floats64,b::Float64)=0

That just tells Julia that the “+” operator takes two Float64 variables and returns Int64 “0”

If that is WHAT YOU WANT then Julia will give it to you.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [May 24, 2019, 10:20pm UTC](https://discourse.julialang.org/t/how-to-avoid-the-2-allocations-for-any-struct/24590/10 "2019-05-24T22:20:22Z")

</div>

This is called ‘type piracy’, @StevenSiew, and is _strongly_ discouraged.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [May 24, 2019, 10:29pm UTC](https://discourse.julialang.org/t/how-to-avoid-the-2-allocations-for-any-struct/24590/11 "2019-05-24T22:29:18Z")

</div>

I can’t immediately tell why you are getting two allocations, it seems a bit odd. But I wonder about the use of `@inline` annotation. I’ve never seen it used like that. You normally use it to mark functions for inlining.

It probably doesn’t have anything to do with your issue, but I can’t see it helping.

---

<div class="post-metadata">

**Author:** ![Jean\_Michel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jean_michel/32/8282_2.png) [@Jean\_Michel](https://discourse.julialang.org/u/Jean_Michel)\
**Post date:** [May 24, 2019, 10:32pm UTC](https://discourse.julialang.org/t/how-to-avoid-the-2-allocations-for-any-struct/24590/12 "2019-05-24T22:32:01Z")

</div>

sorry. inline was a typo for inbounds made when I copied the code by hand. Fixed.

---

<div class="post-metadata">

**Author:** ![StevenSiew](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevensiew/32/218393_2.png) [@StevenSiew](https://discourse.julialang.org/u/StevenSiew)\
**Post date:** [May 24, 2019, 10:33pm UTC](https://discourse.julialang.org/t/how-to-avoid-the-2-allocations-for-any-struct/24590/13 "2019-05-24T22:33:50Z")

</div>

Maybe define your type as

Perm = Tuple{Vector{Int}}

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [May 24, 2019, 10:40pm UTC](https://discourse.julialang.org/t/how-to-avoid-the-2-allocations-for-any-struct/24590/14 "2019-05-24T22:40:56Z")

</div>

It’s possible that there is some benchmarking artefact, even though you seem to interpolate correctly. Perhaps you can try to wrap your tests in functions to see if it makes a difference.

---

<div class="post-metadata">

**Author:** ![ericphanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ericphanson/32/215186_2.png) [@ericphanson](https://discourse.julialang.org/u/ericphanson)\
**Post date:** [May 24, 2019, 10:45pm UTC](https://discourse.julialang.org/t/how-to-avoid-the-2-allocations-for-any-struct/24590/15 "2019-05-24T22:45:46Z")

</div>

This doesn’t directly answer your question, but if you’re dealing with lots of small vectors, [StaticArrays](https://github.com/JuliaArrays/StaticArrays.jl) will likely help performance a lot! However, some things like `sort` are not defined. To work around that, I use [TupleTools](https://github.com/Jutho/TupleTools.jl) to provide e.g. an allocation-free sort method:

```julia
using StaticArrays, TupleTools
import Base.sort
sort(p::SVector{d,T}; rev::Bool = false) where {d,T} = SVector{d,T}(TupleTools.sort(Tuple(p); rev=rev))

```

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [May 24, 2019, 11:24pm UTC](https://discourse.julialang.org/t/how-to-avoid-the-2-allocations-for-any-struct/24590/16 "2019-05-24T23:24:19Z")

</div>

No you can’t get rid of the allocation in this context but that doesn’t really matter since it can be optimal zed out if the function is inlined.

---

<div class="post-metadata">

**Author:** ![Jean\_Michel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jean_michel/32/8282_2.png) [@Jean\_Michel](https://discourse.julialang.org/u/Jean_Michel)\
**Post date:** [May 24, 2019, 11:27pm UTC](https://discourse.julialang.org/t/how-to-avoid-the-2-allocations-for-any-struct/24590/17 "2019-05-24T23:27:41Z")

</div>

Do I have to declare the function @inline explicitly or will the inlining happen automatically?

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [May 25, 2019, 5:34pm UTC](https://discourse.julialang.org/t/how-to-avoid-the-2-allocations-for-any-struct/24590/18 "2019-05-25T17:34:30Z")

</div>

Inlining mostly happens automatically, if the compiler decides that it’s worthwhile. But you can ask it more forcefully with `@inline` (not sure if that will absolutely guarantee inlining, though).

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [May 26, 2019, 6:06am UTC](https://discourse.julialang.org/t/how-to-avoid-the-2-allocations-for-any-struct/24590/19 "2019-05-26T06:06:22Z")

</div>

I think that one should be somewhat cautious with overriding the compiler’s inline decisions.

Even if it happens to yield an improvement in a benchmark with the current Julia version, the compiler improves a lot with every release under the hood, so unless these choices are revisited from time to time (which rarely ever happens in practice) they can easily end up forcing something that is suboptimal within 4–12 months, which is usually much shorter than the lifespan of most code.

There are packages out there with code that have a ton of `@inline` directives dating from the 0.5–0.6 era, which may no longer be necessary or optimal.

---

<div class="post-metadata">

**Author:** ![oxinabox](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oxinabox/32/206603_2.png) [@oxinabox](https://discourse.julialang.org/u/oxinabox)\
**Post date:** [May 26, 2019, 7:46am UTC](https://discourse.julialang.org/t/how-to-avoid-the-2-allocations-for-any-struct/24590/20 "2019-05-26T07:46:32Z")

</div>

> [@StevenSiew](#):
>
> `Perm = Tuple{Vector{Int}}`

or

> [@Jean\_Michel](#):
>
> `Perm=Vector{Int}`

Both result in type-piracy when you do:

> [@StevenSiew](#):
>
> \*(a::Perm,b::Perm) = mult(a,b)

You need to do:

```julia-auto
struct Perm
    data:: Vector{Int}
end

```

and appropriately access the fields.  
Extension via composition

[Next page](https://discourse.julialang.org/t/how-to-avoid-the-2-allocations-for-any-struct/24590.md?page=2)
