So, the problem is that the function has expressions of the form a+b+c+d+e+f+g+h+...
. Julia treats + specially, it’s parsed as an n-ary function +(a,b,c,d,e,f,g,h,...)
. This has some advantages, for instance for macro developers, but also some disadvantages.
As Kristoffer points out, when there are too many arguments (I don’t remember the limit, 20?), things are allocated. This happens for every function with many arguments, not just +
. The parsing can be seen by dumping such an expression:
julia> dump( :(a + b + c + d) )
Expr
head: Symbol call
args: Array{Any}((5,))
1: Symbol +
2: Symbol a
3: Symbol b
4: Symbol c
5: Symbol d
This happens before julia looks at what +
actually means, it’s just an infix operator which is parsed to an n-ary function. This is a special treatment for +
, not given to other operators (other than *
). Unless there are too many arguments, the compiler will optimize away the function calls, and just emit a series of add instructions.
If we use ⊕
it looks like:
dump( :(a ⊕ b ⊕ c ⊕ d) )
Expr
head: Symbol call
args: Array{Any}((3,))
1: Symbol ⊕
2: Expr
head: Symbol call
args: Array{Any}((3,))
1: Symbol ⊕
2: Expr
head: Symbol call
args: Array{Any}((3,))
1: Symbol ⊕
2: Symbol a
3: Symbol b
3: Symbol c
3: Symbol d
I.e., a series of binary calls ⊕(⊕(⊕(a,b),c),d)
. This happens before the actual meaning of ⊕
is used by Julia, even if you have actually set ⊕
to mean the same thing as +
with the assignment ⊕ = +
. Each ⊕
is now a binary call which will easily be optimized away to yield add instructions.
You can see the functions used by Julia by giving the commands:
@edit 1 + 2
and
@edit 1 + 2 + 3 + 4 + 5
and the actual instruction sequence it compiles to with:
@code_native 1 + 2 + 3 + 4 + 5