# Improper function nesting causes boxing/runtime dispatch?

**URL:** https://discourse.julialang.org/t/improper-function-nesting-causes-boxing-runtime-dispatch/114307
**Category:** General Usage
**Tags:** dispatch, function, type-stability, box
**Created:** [May 15, 2024, 4:19pm UTC](https://discourse.julialang.org/t/improper-function-nesting-causes-boxing-runtime-dispatch/114307 "2024-05-15T16:19:49Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![bremez](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bremez/32/38777_2.png) [@bremez](https://discourse.julialang.org/u/bremez)
#### Post date: [May 15, 2024, 4:19pm UTC](https://discourse.julialang.org/t/improper-function-nesting-causes-boxing-runtime-dispatch/114307/1 "2024-05-15T16:19:49Z")

</div>

Note the code example below:

```julia
struct Radix{N} 
    Radix(n::Integer) = new{n}();
end

# Nesting: testfunc! -> _add, _addpositions
function testfunc!(array, num, radix)
    
    _add(a, b, ::Radix{2}) = a ⊻ b
    _add(a, b, ::Radix{radix}) where radix = mod(a+b, radix)
    
    function _add_positions(array, a, b) 
        array[b] = _add(array[a], array[b], radix)
    end
    
    for _ in 1:num
        a,b = rand(1:length(array)), rand(1:length(array))
        _add_positions(array, a, b)
    end
end

# Nesting: testfunc! -> _addpositions -> _add
function testfunc2!(array, num, radix)
    
    function _add_positions(array, a, b) 
        _add(a, b, ::Radix{2}) = a ⊻ b
        _add(a, b, ::Radix{radix}) where radix = mod(a+b, radix)
        array[b] = _add(array[a], array[b], radix)
    end
    
    for _ in 1:num
        a,b = rand(1:length(array)), rand(1:length(array))
        _add_positions(array, a, b)
    end
end

# Nesting: testfunc! -> _add, _addpositions
function testfunc3!(array, num, radix)
    
    #_add(a, b, ::Radix{2}) = a ⊻ b # Commented out - so no dispatch ambiguity
    _add(a, b, ::Radix{radix}) where radix = mod(a+b, radix)
    
    function _add_positions(array, a, b) 
        array[b] = _add(array[a], array[b], radix)
    end
    
    for _ in 1:num
        a,b = rand(1:length(array)), rand(1:length(array))
        _add_positions(array, a, b)
    end
end

```

which benchmarks as follows:

```julia
arr = rand(0:1, 1024);
@btime testfunc!(arr, 1000, Radix(5))
@btime testfunc2!(arr, 1000, Radix(5))
@btime testfunc3!(arr, 1000, Radix(5))

# 117.200 μs (439 allocations: 6.86 KiB)
# 13.300 μs (0 allocations: 0 bytes)
# 17.200 μs (0 allocations: 0 bytes)

```

Note specifically the extra allocations. A `@code_warntype` check of `testfunc!` shows that `_add` itself gets boxed. Why does this happen, and why does it not in `testfunc2!` (which can receive the value of `radix` without boxing)? Once only one definition of `_add` exists, see `testfunc3!`, the problem is resolved.

---

<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: [May 15, 2024, 7:36pm UTC](https://discourse.julialang.org/t/improper-function-nesting-causes-boxing-runtime-dispatch/114307/2 "2024-05-15T19:36:47Z")

</div>

See [Performance Tips · The Julia Language](https://docs.julialang.org/en/v1/manual/performance-tips/#Be-aware-of-when-Julia-avoids-specializing)

---

<div class="post-metadata">

### Author: ![bremez](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bremez/32/38777_2.png) [@bremez](https://discourse.julialang.org/u/bremez)
#### Post date: [May 16, 2024, 2:16am UTC](https://discourse.julialang.org/t/improper-function-nesting-causes-boxing-runtime-dispatch/114307/3 "2024-05-16T02:16:53Z")

</div>

@Oscar_Smith so if I understand right, in the first implementation ‘\_add’ is implicitly passed as an argument to a lifted realization of ‘\_add\_positions’? Then, since its type is ‘Function’, ‘\_add\_positions’ doesn’t specialize, and since it’s passed implicitly I cannot add the explicit specialization directive the manual suggests?

The documentation mentions this problem won’t show up with ‘@code\_warntype’ - this fact indeed stumped my search for where these allocations were coming from! (I had guessed it arose from the capturing of ‘radix’)

---

<div class="post-metadata">

### Author: ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)
#### Post date: [May 17, 2024, 7:00am UTC](https://discourse.julialang.org/t/improper-function-nesting-causes-boxing-runtime-dispatch/114307/4 "2024-05-17T07:00:01Z")

</div>

I think @Oscar_Smith just linked the wrong section of the Performance Tips. [This](https://docs.julialang.org/en/v1/manual/performance-tips/#man-performance-captured) should be the right one.
