# How to force a small allocation?

**URL:** <https://discourse.julialang.org/t/how-to-force-a-small-allocation/128487>\
**Category:** General Usage\
**Created:** [April 28, 2025, 11:31am UTC](https://discourse.julialang.org/t/how-to-force-a-small-allocation/128487 "2025-04-28T11:31:26Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![photor](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/photor/32/14343_2.png) [@photor](https://discourse.julialang.org/u/photor)\
**Post date:** [April 28, 2025, 11:31am UTC](https://discourse.julialang.org/t/how-to-force-a-small-allocation/128487/1 "2025-04-28T11:31:26Z")

</div>

A MWE:

```julia
function test()
    Bool[]
    return nothing
end

@time test()

```

results in

```julia
  0.000007 seconds (1 allocation: 64 bytes)

```

as desired in Julia 1.7.3. But this method doesn’t work in 1.10.9, resulting in no allocation. What’s the universal method?

---

<div class="post-metadata">

**Author:** ![ForceBru](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/forcebru/32/21389_2.png) [@ForceBru](https://discourse.julialang.org/u/ForceBru)\
**Post date:** [April 28, 2025, 11:44am UTC](https://discourse.julialang.org/t/how-to-force-a-small-allocation/128487/2 "2025-04-28T11:44:46Z")

</div>

You instantiate an empty vector and do nothing with it. I guess the 1.10 compiler optimizes the code better and thus doesn’t create the unused vector at all. Seems like a useful performance optimization to me.

---

<div class="post-metadata">

**Author:** ![photor](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/photor/32/14343_2.png) [@photor](https://discourse.julialang.org/u/photor)\
**Post date:** [April 28, 2025, 12:01pm UTC](https://discourse.julialang.org/t/how-to-force-a-small-allocation/128487/3 "2025-04-28T12:01:27Z")

</div>

But I don’t want it to be too smart, at least for my purpose.

---

<div class="post-metadata">

**Author:** ![foobar\_lv2](https://avatars.discourse-cdn.com/v4/letter/f/ee59a6/32.png) [@foobar\_lv2](https://discourse.julialang.org/u/foobar_lv2)\
**Post date:** [April 28, 2025, 12:12pm UTC](https://discourse.julialang.org/t/how-to-force-a-small-allocation/128487/4 "2025-04-28T12:12:52Z")

</div>

You need to explain your purpose then, otherwise we can’t help you.

---

<div class="post-metadata">

**Author:** ![barucden](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/barucden/32/26154_2.png) [@barucden](https://discourse.julialang.org/u/barucden)\
**Post date:** [April 28, 2025, 12:21pm UTC](https://discourse.julialang.org/t/how-to-force-a-small-allocation/128487/5 "2025-04-28T12:21:42Z")

</div>

There are some general guidelines though, no? For example, if the vector is used in some way, then the vector has to be created:

```julia
f() = sum(rand(10))

```

I’d think this will always allocate.

---

<div class="post-metadata">

**Author:** ![VinceNeede](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vinceneede/32/215744_2.png) [@VinceNeede](https://discourse.julialang.org/u/VinceNeede)\
**Post date:** [April 28, 2025, 12:23pm UTC](https://discourse.julialang.org/t/how-to-force-a-small-allocation/128487/6 "2025-04-28T12:23:34Z")

</div>

I don’t know the purpose, but this should work (it does for 1.11.5 at least):

```julia
function test()
     sizehint!(Bool[], 0)
    return nothing
end

@allocations test() # 1 allocation

```

---

<div class="post-metadata">

**Author:** ![photor](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/photor/32/14343_2.png) [@photor](https://discourse.julialang.org/u/photor)\
**Post date:** [April 28, 2025, 12:41pm UTC](https://discourse.julialang.org/t/how-to-force-a-small-allocation/128487/7 "2025-04-28T12:41:28Z")

</div>

I want to know the recursion times of my recursive code, when using `@btime` to benchmark it.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [April 28, 2025, 12:50pm UTC](https://discourse.julialang.org/t/how-to-force-a-small-allocation/128487/8 "2025-04-28T12:50:44Z")

</div>

> [@photor](#):
>
> the recursion times of my recursive code

What does this mean if it’s not directly profiling said code, and what does it have to do with forcing a `Bool[]` allocation to occur?

---

<div class="post-metadata">

**Author:** ![foobar\_lv2](https://avatars.discourse-cdn.com/v4/letter/f/ee59a6/32.png) [@foobar\_lv2](https://discourse.julialang.org/u/foobar_lv2)\
**Post date:** [April 28, 2025, 2:56pm UTC](https://discourse.julialang.org/t/how-to-force-a-small-allocation/128487/9 "2025-04-28T14:56:52Z")

</div>

I think you should give even more context. You can of course do something like

```julia
julia> function test()
           a = Bool[]
           GC.@preserve a ccall(:memchr, Ptr{Nothing}, (Ptr{Nothing}, Cint, Csize_t), pointer_from_objref(a), 0, 0)
           return nothing
       end

```

But that involves the full function call overhead of maybe ~15 cycles, and makes the compiler forget a lot of info (i.e. it doesn’t play well with surrounding LICM because the compiler must assume that the foreign call clobbers memory). So does this really reflect your real workload? We cannot help you with that without more context on what your real workloads are.

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [April 28, 2025, 3:13pm UTC](https://discourse.julialang.org/t/how-to-force-a-small-allocation/128487/10 "2025-04-28T15:13:18Z")

</div>

I mean, an obvious way to make sure the allocation isn’t removed is to actually use it, without doing anything else overcomplicated:

```julia
julia> test() = Bool[]
test (generic function with 1 method)

julia> @time test()
  0.000001 seconds (1 allocation: 32 bytes)
Bool[]

```

But I concur with the request above to explain better what you ultimately want to achieve and avoid [XY problems](https://xyproblem.info/).

---

<div class="post-metadata">

**Author:** ![photor](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/photor/32/14343_2.png) [@photor](https://discourse.julialang.org/u/photor)\
**Post date:** [April 28, 2025, 3:55pm UTC](https://discourse.julialang.org/t/how-to-force-a-small-allocation/128487/11 "2025-04-28T15:55:31Z")

</div>

Thank you guys for helping. This is a more complete example:

```julia
function Fib(n)
    Bool[]
    if n==0 || n==1
        return 1
    else
        return Fib(n-1)+Fib(n-2)
    end
end

@time Fib(5)

```

gives the result

```julia
  0.000004 seconds (15 allocations: 960 bytes)
8

```

in Julia 1.7.3, which is what I want, but it doesn’t work in 1.10.9.

---

<div class="post-metadata">

**Author:** ![foobar\_lv2](https://avatars.discourse-cdn.com/v4/letter/f/ee59a6/32.png) [@foobar\_lv2](https://discourse.julialang.org/u/foobar_lv2)\
**Post date:** [April 28, 2025, 4:07pm UTC](https://discourse.julialang.org/t/how-to-force-a-small-allocation/128487/12 "2025-04-28T16:07:07Z")

</div>

But that example is nonsense, you’re just abusing the global allocation counter for counting the number of invocations. Just do

```julia
const counter = Ref(0)
function Fib(n)
    counter[] += 1
    if n==0 || n==1
        return 1
    else
        return Fib(n-1)+Fib(n-2)
    end
end

tic = counter[];
 Fib(5)
toc = counter[]; @show toc - tic

```

---

<div class="post-metadata">

**Author:** ![photor](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/photor/32/14343_2.png) [@photor](https://discourse.julialang.org/u/photor)\
**Post date:** [April 28, 2025, 4:09pm UTC](https://discourse.julialang.org/t/how-to-force-a-small-allocation/128487/13 "2025-04-28T16:09:24Z")

</div>

But your method doesn’t work with `@btime`, right?

---

<div class="post-metadata">

**Author:** ![mikmoore](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikmoore/32/31109_2.png) [@mikmoore](https://discourse.julialang.org/u/mikmoore)\
**Post date:** [April 28, 2025, 4:53pm UTC](https://discourse.julialang.org/t/how-to-force-a-small-allocation/128487/14 "2025-04-28T16:53:43Z")

</div>

You can use [the `setup` keyword to `@btime`](https://juliaci.github.io/BenchmarkTools.jl/stable/manual/#Setup-and-teardown-phases) to reset mutable state between runs, if that’s the issue.

If your goal is just to count calls, you could return the count of `Fib` as a second argument. The count of a particular call would be the sum of the counts of each of the two recursive calls (or 1 in the base case). This could count the calls using only local variables.

---

<div class="post-metadata">

**Author:** ![Zentrik](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zentrik/32/35409_2.png) [@Zentrik](https://discourse.julialang.org/u/Zentrik)\
**Post date:** [April 28, 2025, 6:22pm UTC](https://discourse.julialang.org/t/how-to-force-a-small-allocation/128487/15 "2025-04-28T18:22:25Z")

</div>

This can be optimised out, progress is certainly being made towards that happening if it hasn’t already e.g. [https://github.com/JuliaLang/julia/pull/55913](https://github.com/JuliaLang/julia/pull/55913)

---

<div class="post-metadata">

**Author:** ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)\
**Post date:** [April 28, 2025, 7:26pm UTC](https://discourse.julialang.org/t/how-to-force-a-small-allocation/128487/16 "2025-04-28T19:26:37Z")

</div>

> [@mikmoore](#):
>
> If your goal is just to count calls, you could return the count of `Fib` as a second argument.

Implementation:

```julia-repl
julia> function fib(n)
           if (n == 0) || (n == 1)
               return (1, 1)
           end
           f1, c1 = fib(n - 1)
           f2, c2 = fib(n - 2)
           return (f1 + f2, c1 + c2 + 1)
       end
fib (generic function with 1 method)

julia> fib(5)
(8, 15)

```

---

<div class="post-metadata">

**Author:** ![matthias314](https://avatars.discourse-cdn.com/v4/letter/m/a88e4f/32.png) [@matthias314](https://discourse.julialang.org/u/matthias314)\
**Post date:** [April 28, 2025, 10:25pm UTC](https://discourse.julialang.org/t/how-to-force-a-small-allocation/128487/17 "2025-04-28T22:25:09Z")

</div>

> [@mikmoore](#):
>
> You can use [the `setup` keyword to `@btime`](https://juliaci.github.io/BenchmarkTools.jl/stable/manual/#Setup-and-teardown-phases) to reset mutable state between runs, if that’s the issue.

The setup code is executed once per sample, but a sample may contain many evaluations. You have to add `evals = 1` to `@btime` to get a single evaluation per sample. In my experience, this leads to quite inaccurate results for short runtimes.

---

<div class="post-metadata">

**Author:** ![photor](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/photor/32/14343_2.png) [@photor](https://discourse.julialang.org/u/photor)\
**Post date:** [April 29, 2025, 2:25am UTC](https://discourse.julialang.org/t/how-to-force-a-small-allocation/128487/18 "2025-04-29T02:25:03Z")

</div>

Thanks a lot. This works well for me, just bringing ~250 ns overhead per call on my machine.

---

<div class="post-metadata">

**Author:** ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)\
**Post date:** [April 29, 2025, 3:49am UTC](https://discourse.julialang.org/t/how-to-force-a-small-allocation/128487/19 "2025-04-29T03:49:21Z")

</div>

Keep in mind that the language doesn’t provide any guarantees about allocations. They can be optimized away, as you observed, but in other cases, there can be more of them than you expect. Even with @VinceNeede’s solution, this is hardly a reliable way of counting the number of function calls.

> [@photor](#):
>
> But your method doesn’t work with `@btime`, right?

Other people have mentioned `setup`, but the easiest solution here is just to reset the counter as part of the benchmark:

```julia-repl
julia> const counter = Ref(0);

julia> function fib(n)
           counter[] += 1
           if (n == 0) || (n == 1)
               return 1
           else
               return fib(n - 1) + fib(n - 2)
           end
       end
fib (generic function with 1 method)

julia> @btime begin
           $counter[] = 0
           f = fib(5)
           (f, $counter[])
       end
  11.261 ns (0 allocations: 0 bytes)
(8, 15)

```
