# Increase in allocations with Julia v1.11-beta

**URL:** <https://discourse.julialang.org/t/increase-in-allocations-with-julia-v1-11-beta/112838>\
**Category:** Internals & Design\
**Tags:** performance, arrays\
**Created:** [April 11, 2024, 2:19pm UTC](https://discourse.julialang.org/t/increase-in-allocations-with-julia-v1-11-beta/112838 "2024-04-11T14:19:59Z")\
**Posts on this page:** 20\
**Page:** 2

<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:** [April 14, 2024, 10:34pm UTC](https://discourse.julialang.org/t/increase-in-allocations-with-julia-v1-11-beta/112838/21 "2024-04-14T22:34:46Z")

</div>

they were previously tracked. before, the data was in the same allocation as the header which is sometimes better and sometimes worse (if the array is resized, it can waste a lot of memory)

---

<div class="post-metadata">

**Author:** ![Elrod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elrod/32/22461_2.png) [@Elrod](https://discourse.julialang.org/u/Elrod)\
**Post date:** [April 14, 2024, 11:58pm UTC](https://discourse.julialang.org/t/increase-in-allocations-with-julia-v1-11-beta/112838/22 "2024-04-14T23:58:54Z")

</div>

Only `Array{T,1}` can actually be resized, so `Array{T,N}`, `N == 0 || N >= 2` also involving a `mutable struct` instead of plain `struct` seems unnecessary.

Would perhaps be nice if we had a distinction between non-resizeable mathematical arrays, and resizable linear collections, but that would be very breaking and thus is not happening.

Would be cool if there were some way to place constraints based on parameters:

```julia
struct MathArray{T,N} <: DenseArray{T,N}
    data::Memory{T}
    size::NTuple{N,Int}
end
mutable struct LinearCollection{T} <: DenseVector{T}
    data::Memory{T}
    length::Int
end

const Array{T,N} = # somehow make it `LinearCollection{T}` when `N == 1`, and `MathArray{T,N}` otherwise. 

```

---

<div class="post-metadata">

**Author:** ![jameson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jameson/32/23_2.png) [@jameson](https://discourse.julialang.org/u/jameson)\
**Post date:** [April 15, 2024, 1:33am UTC](https://discourse.julialang.org/t/increase-in-allocations-with-julia-v1-11-beta/112838/23 "2024-04-15T01:33:37Z")

</div>

On the other hand, we could permit resizing other dimensions too, as we currently pay all of that cost to be possible (seems to be very little actually except for the allocation itself) but currently gives none of that flexibility of that. And except for Matrix, it isn’t generally a beneficial idea to allocate it inlined anyways, as the struct starts to get quite large.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [April 15, 2024, 11:35am UTC](https://discourse.julialang.org/t/increase-in-allocations-with-julia-v1-11-beta/112838/24 "2024-04-15T11:35:16Z")

</div>

FWIW, this is the result of a larger calculation:

1.10.2:

49.666810 seconds (105.84 k allocations: 872.115 MiB)

1.11:

47.559673 seconds (229.30 k allocations: 962.446 MiB, 0.58% gc time, 11 lock conflicts)

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [April 15, 2024, 12:15pm UTC](https://discourse.julialang.org/t/increase-in-allocations-with-julia-v1-11-beta/112838/25 "2024-04-15T12:15:39Z")

</div>

Did you use multi-threaded garbage collection? I would suggest to launch Julia with

```julia
julia --gcthreads=7,1

```

if you have 8 fast physical cores…

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [April 15, 2024, 12:26pm UTC](https://discourse.julialang.org/t/increase-in-allocations-with-julia-v1-11-beta/112838/26 "2024-04-15T12:26:25Z")

</div>

Just to be clear: Memory has fixed size but is not immutable.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [April 15, 2024, 1:34pm UTC](https://discourse.julialang.org/t/increase-in-allocations-with-julia-v1-11-beta/112838/27 "2024-04-15T13:34:30Z")

</div>

I don´t have (almost) GC in those calculations. (they are parallel - 10 threads there).

In any case, this is the result starting Julia with `julia --gcthreads=9,1`. Here 5 successive runs (discarding the first one, which has ~5% compilation):

1.10.2:

47.999261 seconds (105.75 k allocations: 872.109 MiB)  
46.349978 seconds (105.78 k allocations: 872.106 MiB, 0.14% gc time)  
45.914514 seconds (105.70 k allocations: 872.104 MiB, 0.09% gc time)  
49.659957 seconds (105.89 k allocations: 872.119 MiB)  
49.863240 seconds (105.85 k allocations: 872.119 MiB, 0.01% gc time)

1.11:

48.109827 seconds (229.17 k allocations: 962.447 MiB, 0.56% gc time, 13 lock conflicts)  
51.137695 seconds (229.35 k allocations: 962.458 MiB, 0.55% gc time, 13 lock conflicts)  
47.078975 seconds (229.14 k allocations: 962.445 MiB, 0.81% gc time, 12 lock conflicts)  
52.507213 seconds (229.32 k allocations: 962.457 MiB, 0.48% gc time, 14 lock conflicts)  
47.022936 seconds (229.06 k allocations: 962.440 MiB, 0.85% gc time, 10 lock conflicts)

I would say that the differences are not really meanginful, probably.

ps: I don’t like the “conflicts” word there, seems to imply there’s a bug. Maybe “lock events”?

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [April 15, 2024, 1:45pm UTC](https://discourse.julialang.org/t/increase-in-allocations-with-julia-v1-11-beta/112838/28 "2024-04-15T13:45:14Z")

</div>

> [@StefanKarpinski](#):
>
> Just to be clear: Memory has fixed size but is not immutable.

The mutable static arrays of `StaticArrays` aren’t either, but they have the size in the type signature, which Memory does not.

By the way, is that because it would explode compilation times, as with static arrays?

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [April 15, 2024, 1:47pm UTC](https://discourse.julialang.org/t/increase-in-allocations-with-julia-v1-11-beta/112838/29 "2024-04-15T13:47:53Z")

</div>

Yes, putting the size in the type would cause the compiler to try to specialize on every size. Maybe worthwhile for a few small sizes but generally a waste of effort.

---

<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:** [April 15, 2024, 4:16pm UTC](https://discourse.julialang.org/t/increase-in-allocations-with-julia-v1-11-beta/112838/30 "2024-04-15T16:16:24Z")

</div>

In C++ array size is part of the type, afaiu. Don’t the C++ compilers specialize on size?

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [April 15, 2024, 7:57pm UTC](https://discourse.julialang.org/t/increase-in-allocations-with-julia-v1-11-beta/112838/31 "2024-04-15T19:57:42Z")

</div>

FWIW - part 2. A very comprehensive benchmark of CellListMap.jl shows the results below. Most generally, small but consistent improvements in the performence of 1.11-beta1 relative to 1.10.2 (blue lines slightly below red one). Thus, for my purposes, this will be an improvement :-).

 ![image](https://global.discourse-cdn.com/julialang/original/3X/4/1/416b2a203342d8d6b01127b52a46fd005e07e335.png)

(the benchmark consists in computing the histogram of pairwise velocities of “galaxies”, with true density, in the case of “constant density”: [GitHub - lmiq/PairVelocities](https://github.com/lmiq/PairVelocities)).

---

<div class="post-metadata">

**Author:** ![Elrod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elrod/32/22461_2.png) [@Elrod](https://discourse.julialang.org/u/Elrod)\
**Post date:** [April 16, 2024, 4:26am UTC](https://discourse.julialang.org/t/increase-in-allocations-with-julia-v1-11-beta/112838/32 "2024-04-16T04:26:19Z")

</div>

`std::array` is statically sized (and stack allocated).

`std::vector<T>` is closer to `Vector{T}` in Julia. It is dynamically sized, and consists of two parts:

- the data pointer containing the `T`s. This is generally heap allocated (technically there is a second type parameter with a default arg, i.e. it is `std::vector<T,A=std::allocator<T>>`, so it’s really up to that allocator).
- the header with that pointer, plus a size and capacity field. This is generally stack allocated.

In Julia, the capacity is with the data as part of `Memory{T}`, and the header gets heap allocated when it escapes (but shouldn’t otherwise).

To be pedantic, the [boost::container:::devector](https://www.boost.org/doc/libs/1_80_0/doc/html/boost/container/devector.html) is actually closer to Julia’s `Vector{T}`, because the two of them support fast `push`ing and `pop`ing on both ends, while `std::vector<T>` is only fast at the back.

Plenty of libraries provide their own types, including optionally mixing dynamic and static dimensions, like Eigen.  
There are also dynamic vector types with some extra stack space they can use to avoid a heap allocation if the overall size is smaller. E.g., [boost::container::small\_vector](https://www.boost.org/doc/libs/1_80_0/doc/html/boost/container/small_vector.html).  
There are also fixed-capacity vectors (in boost, plus a proposal for C++26), in case you know the maximum possible size (and that size is small enough that it’s worth always stack allocating that much instead of heap allocating however much you actually need).

---

<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:** [April 16, 2024, 5:27am UTC](https://discourse.julialang.org/t/increase-in-allocations-with-julia-v1-11-beta/112838/33 "2024-04-16T05:27:47Z")

</div>

> [@Elrod](#):
>
> `std::array` is statically sized (and stack allocated).

But do you know if the C++ compilers ‘specialize’ on the size of arrays similarly to how the Julia compiler would?

---

<div class="post-metadata">

**Author:** ![Elrod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elrod/32/22461_2.png) [@Elrod](https://discourse.julialang.org/u/Elrod)\
**Post date:** [April 16, 2024, 5:53am UTC](https://discourse.julialang.org/t/increase-in-allocations-with-julia-v1-11-beta/112838/34 "2024-04-16T05:53:18Z")

</div>

Yes, they specialize. C++ compilers monomorphize, compiling separate code for every set of types, just like Julia.

Here is an example:

> **[Compiler Explorer - C++](https://godbolt.org/z/9MYqTfPcK)**
>
> constexpr auto sum(auto v){
> decltype(v\[0\] + v\[1\]) s{};
> for (auto x : v) s += x;
> return s;
> }
> 
> static\_assert(sum(std::array{1,2,3}) == 6);
> 
> // create some instantiations
> auto foo(std::array v){
> return sum(v);
> }
> auto foo(std::array v){
> ...

Note that `sum` inlines into each of the `foo`s.  
Each call to `sum` with different argument types compiles different code.  
Note this works for an arbitrary number of arguments, I just did `sum` to keep it simple.

One of `StaticArray`s (and `Tuple`’s) problems are that a lot of code dealing with them are fully unrolled in Julia, which hurts compile times of these individual specializations somewhat unnecessarily.

Still, this is one of the reasons C++'s compile times aren’t good.

One cool thing about the C++ assembly is that for the length-2 `array`s, they were passed in registers instead of the stack (note the lack of loading from `rsp`, instead immediately using registers).  
Arrays of length 3 or more go back to using the stack, though.

---

<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:** [April 20, 2024, 3:14am UTC](https://discourse.julialang.org/t/increase-in-allocations-with-julia-v1-11-beta/112838/35 "2024-04-20T03:14:56Z")

</div>

It just crossed my mind that an array type that doesn’t depend on `Array`, (thus avoiding the extra indirection and allocation costs) should be very easy to define while retaining almost all of the array functionality (because most of the array functionality is defined for abstract types). The package is here, but it can’t be registered until Julia v1.11 gets released: [Neven Sajko / FixedSizeColumnMajorDenseArrays.jl · GitLab](https://gitlab.com/nsajko/FixedSizeColumnMajorDenseArrays.jl)

EDIT: the size here is fixed at run time, unlike with @giordano’s FixedSizeArrays.jl where the size seems to be stored in the type domain (thus it’s a compile time constant) EDIT2: actually, the size is stored as a value in both packages, it’s just that the README there is perhaps misleading

EDIT3: just use Giordano’s package instead, I’ll probably delete my repo

---

<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:** [April 20, 2024, 3:20am UTC](https://discourse.julialang.org/t/increase-in-allocations-with-julia-v1-11-beta/112838/36 "2024-04-20T03:20:13Z")

</div>

see also [GitHub - giordano/FixedSizeArrays.jl](https://github.com/giordano/FixedSizeArrays.jl)

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [April 20, 2024, 3:21am UTC](https://discourse.julialang.org/t/increase-in-allocations-with-julia-v1-11-beta/112838/37 "2024-04-20T03:21:00Z")

</div>

Very nice!

But I would suggest to use a shorter name, like `FastFixedSizeArrays` or `FixedSizeCMDArrays`, otherwise it becomes a pain to type…

---

<div class="post-metadata">

**Author:** ![Elrod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elrod/32/22461_2.png) [@Elrod](https://discourse.julialang.org/u/Elrod)\
**Post date:** [April 20, 2024, 3:40am UTC](https://discourse.julialang.org/t/increase-in-allocations-with-julia-v1-11-beta/112838/38 "2024-04-20T03:40:19Z")

</div>

> [@nsajko](#):
>
> EDIT: the size here is fixed at run time, unlike with @giordano’s [FixedSizeArrays.jl](https://juliahub.com/ui/Packages/General/FixedSizeArrays) where the size seems to be stored in the type domain (thus it’s a compile time constant)

No, they’re runtime values stored as an `NTuple{N,Int}`: [FixedSizeArrays.jl/src/FixedSizeArrays.jl at f8b71ffcf1334c60d2cc7279cb34010964dff387 · JuliaArrays/FixedSizeArrays.jl · GitHub](https://github.com/giordano/FixedSizeArrays.jl/blob/f8b71ffcf1334c60d2cc7279cb34010964dff387/src/FixedSizeArrays.jl#L7)

---

<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:** [April 20, 2024, 3:41am UTC](https://discourse.julialang.org/t/increase-in-allocations-with-julia-v1-11-beta/112838/39 "2024-04-20T03:41:53Z")

</div>

> [@Elrod](#):
>
> No, they’re runtime values

Yeah, I got confused by the README there. Already edited my comment.

---

<div class="post-metadata">

**Author:** ![juthohaegeman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juthohaegeman/32/8620_2.png) [@juthohaegeman](https://discourse.julialang.org/u/juthohaegeman)\
**Post date:** [May 6, 2024, 11:05pm UTC](https://discourse.julialang.org/t/increase-in-allocations-with-julia-v1-11-beta/112838/40 "2024-05-06T23:05:12Z")

</div>

> [@mbauman](#):
>
> No. Just use `Array` unless you’re implementing some fundamental type or are directly working with bytes of… memory.

I found it a bit strange that such a rather significant change is not even mentioned in the release notes, and also seems to have very little documentation.

Is there for example a canonical way to get the `Memory` object associated with an `Array` instance?

[Previous page](https://discourse.julialang.org/t/increase-in-allocations-with-julia-v1-11-beta/112838.md?page=1)

[Next page](https://discourse.julialang.org/t/increase-in-allocations-with-julia-v1-11-beta/112838.md?page=3)
