# Why do functions like similar and copy make 2 allocations for large arrays?

**URL:** <https://discourse.julialang.org/t/why-do-functions-like-similar-and-copy-make-2-allocations-for-large-arrays/117217>\
**Category:** New to Julia\
**Created:** [July 19, 2024, 7:19am UTC](https://discourse.julialang.org/t/why-do-functions-like-similar-and-copy-make-2-allocations-for-large-arrays/117217 "2024-07-19T07:19:01Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![mike1](https://avatars.discourse-cdn.com/v4/letter/m/e19adc/32.png) [@mike1](https://discourse.julialang.org/u/mike1)\
**Post date:** [July 19, 2024, 7:19am UTC](https://discourse.julialang.org/t/why-do-functions-like-similar-and-copy-make-2-allocations-for-large-arrays/117217/1 "2024-07-19T07:19:01Z")

</div>

Hi, Julia Community!

I am trying to wrap my head around this one: Functions like `similar` and `copy` seem to make 2 allocations if the array is sufficiently large. Can you help me understand why?

```julia-repl
julia> using BenchmarkTools

julia> a, b = rand(100), rand(10000);

julia> @btime similar($a)
  35.473 ns (1 allocation: 896 bytes)
100-element Vector{Float64}:
 2.251444318e-314
 2.251444334e-314
 2.25144435e-314
 ⋮
 0.0
 0.0
 0.0

julia> @btime similar($b)
  54.196 ns (2 allocations: 78.17 KiB)
10000-element Vector{Float64}:
 0.0
 0.0
 0.0
 ⋮
 0.0
 0.0
 0.0

```

I get the same number of allocations for `copy`, which I guess makes sense, because it is probably implemented in terms of `similar`.

Am I simply doing something wrong with the `@btime` macro?  
If this is real, how could I copy an array with just one allocation?  
Or is that not a good idea for reasons I am not aware of?

Cheers  
Mike

---

<div class="post-metadata">

**Author:** ![sylvaticus](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sylvaticus/32/203883_2.png) [@sylvaticus](https://discourse.julialang.org/u/sylvaticus)\
**Post date:** [July 19, 2024, 7:28am UTC](https://discourse.julialang.org/t/why-do-functions-like-similar-and-copy-make-2-allocations-for-large-arrays/117217/2 "2024-07-19T07:28:18Z")

</div>

Just a guess: some implementation detail that changes the undelying low level algoritm (or the array implementation itself) depending on object size ??

---

<div class="post-metadata">

**Author:** ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)\
**Post date:** [July 19, 2024, 7:44am UTC](https://discourse.julialang.org/t/why-do-functions-like-similar-and-copy-make-2-allocations-for-large-arrays/117217/3 "2024-07-19T07:44:33Z")

</div>

Which Julia version are you on? The `Memory` changes of 1.11 are known to cause this behavior

> [@Increase in allocations with Julia v1.11-beta](https://discourse.julialang.org/t/increase-in-allocations-with-julia-v1-11-beta/112838):
>
> Is the number of allocations considered an issue? In my small tests here with my packages I’m not seeing performance regressions, but I systematically see the number of allocations increasing, even when compilation is not involved: 1.10.2: julia\> using CellListMap julia\> x, box = CellListMap.xatomic(10^6); julia\> @btime CellList($x, $box) 244.720 ms (13742 allocations: 139.53 MiB) 1.11: julia\> using CellListMap julia\> x, box = CellListMap.xatomic(10^6); julia\> @btime CellList($x, $box)…

---

<div class="post-metadata">

**Author:** ![mike1](https://avatars.discourse-cdn.com/v4/letter/m/e19adc/32.png) [@mike1](https://discourse.julialang.org/u/mike1)\
**Post date:** [July 19, 2024, 7:49am UTC](https://discourse.julialang.org/t/why-do-functions-like-similar-and-copy-make-2-allocations-for-large-arrays/117217/4 "2024-07-19T07:49:11Z")

</div>

```julia-repl
julia> versioninfo()
Julia Version 1.10.4
Commit 48d4fd48430 (2024-06-04 10:41 UTC)
Build Info:
  Official https://julialang.org/ release
Platform Info:
  OS: macOS (arm64-apple-darwin22.4.0)
  CPU: 10 × Apple M1 Pro
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-15.0.7 (ORCJIT, apple-m1)
Threads: 1 default, 0 interactive, 1 GC (on 8 virtual cores)

```

I am actually not worried about performance, just puzzled, because it seems counterintuitive to me.

PS: The turning point is `2^11`, by the way.

---

<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:** [July 19, 2024, 7:56am UTC](https://discourse.julialang.org/t/why-do-functions-like-similar-and-copy-make-2-allocations-for-large-arrays/117217/5 "2024-07-19T07:56:25Z")

</div>

Yeah, it’s well-known, and it’s ‘always’ been this way. I can’t exactly explain what happens, but you can find the exact size where it occurs by trial and error (I think it’s some length 2^n _edit_: Oops, n=11 as you already found).

I wouldn’t worry about it, unless you are simply curious.

---

<div class="post-metadata">

**Author:** ![nilshg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nilshg/32/2283_2.png) [@nilshg](https://discourse.julialang.org/u/nilshg)\
**Post date:** [July 19, 2024, 8:23am UTC](https://discourse.julialang.org/t/why-do-functions-like-similar-and-copy-make-2-allocations-for-large-arrays/117217/6 "2024-07-19T08:23:52Z")

</div>

This is curious, I see identical output of `@code_llvm` and `@code_native` (modulo some auto-generated function names as far as I can tell), is there a chance that this is a benchmarking artefact?

---

<div class="post-metadata">

**Author:** ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)\
**Post date:** [July 19, 2024, 8:50am UTC](https://discourse.julialang.org/t/why-do-functions-like-similar-and-copy-make-2-allocations-for-large-arrays/117217/7 "2024-07-19T08:50:49Z")

</div>

There is slightly different treatment of memory smaller and larger than 2048:

> <https://github.com/JuliaLang/julia/blob/0e6d7972c62eb1dedaf00ea9b966a0060e2effb8/src/genericmemory.c#L51C4-L64C1>

---

<div class="post-metadata">

**Author:** ![mike1](https://avatars.discourse-cdn.com/v4/letter/m/e19adc/32.png) [@mike1](https://discourse.julialang.org/u/mike1)\
**Post date:** [July 19, 2024, 9:17am UTC](https://discourse.julialang.org/t/why-do-functions-like-similar-and-copy-make-2-allocations-for-large-arrays/117217/8 "2024-07-19T09:17:02Z")

</div>

Thanks [@everyone](https://discourse.julialang.org/groups/everyone) you for your input! For me it was mostly about knowing that I’m not doing something obviously stupid.

The C code really helped for digging deeper. After searching a little bit, I eventually found the corresponding [documentation page](https://docs.julialang.org/en/v1/devdocs/gc/#Allocation), which explains this in quite some detail.
