# \[ANN\] AllocCheck.jl: Static code analysis to prove allocation-free behavior

**URL:** <https://discourse.julialang.org/t/ann-alloccheck-jl-static-code-analysis-to-prove-allocation-free-behavior/106414>\
**Category:** Package Announcements\
**Tags:** package, control, memory-allocation, garbage-collection, realtime\
**Created:** [November 18, 2023, 6:08pm UTC](https://discourse.julialang.org/t/ann-alloccheck-jl-static-code-analysis-to-prove-allocation-free-behavior/106414 "2023-11-18T18:08:29Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [November 18, 2023, 6:08pm UTC](https://discourse.julialang.org/t/ann-alloccheck-jl-static-code-analysis-to-prove-allocation-free-behavior/106414/1 "2023-11-18T18:08:29Z")

</div>

JuliaHub is happy to announce a new open source tool for static code analysis to prove that a Julia function is allocation-free. Use this to ensure that codes are safe for real-time applications, such as how we use it for JuliaSim to analyze SciML control codes!

 ![Screenshot 2023-11-18 at 12.55.42 PM](https://global.discourse-cdn.com/julialang/original/3X/7/6/768c737fc697ff19830c71132cb5ea7372d0a1a6.png)

The primary entry point to check allocations is the macro [`@check_allocs`](https://github.com/JuliaLang/AllocCheck.jl/blob/main/@ref) which is used to annotate a function definition that you’d like to enforce allocation checks for:

```julia
julia> using AllocCheck

julia> @check_allocs multiply(x,y) = x * y
multiply (generic function with 1 method)

julia> multiply(1.5, 2.5) # call automatically checked for allocations
3.75

julia> multiply(rand(3,3), rand(3,3)) # result matrix requires an allocation
ERROR: @check_alloc function encountered 1 errors (1 allocations / 0 dynamic dispatches).

```

To use it, check out the repository in JuliaLang:

> **[GitHub - JuliaLang/AllocCheck.jl: AllocCheck](https://github.com/JuliaLang/AllocCheck.jl)**
>
> AllocCheck. Contribute to JuliaLang/AllocCheck.jl development by creating an account on GitHub.

For more on how Julia is developing for real-time controls applications, check out JuliaSim:

> **[JuliaSim - JuliaHub](https://juliahub.com/products/juliasim/)**
>
> JuliaSim - JuliaHub

Please give all of the credit to the real developers, Cody Tapscott and @gbaraldi.

---

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [November 19, 2023, 8:49am UTC](https://discourse.julialang.org/t/ann-alloccheck-jl-static-code-analysis-to-prove-allocation-free-behavior/106414/2 "2023-11-19T08:49:02Z")

</div>

Turning allocations into errors (with a stack trace)! Very nice!

Fun little historical remark: This was already asked for by @rdeits at JuliaCon London 2018 with a (somewhat) famous reply by @jeff.bezanson!

> **[JuliaRobotics: Making robots walk with Julia | Robin Deits](https://www.youtube.com/live/dmWQtI3DFFo?si=Rbmt7QIRCd28YkVF&t=2286)**
>
> Do you want to build Baymax, Data, or Robby the Robot? Do you want a future with more robots for rescue, delivery, and exploration (and fewer C++ linker erro...

(Relatedly: [A macro that forbids allocation – turning allocation into error · Issue #34248 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/34248))

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [November 19, 2023, 11:10am UTC](https://discourse.julialang.org/t/ann-alloccheck-jl-static-code-analysis-to-prove-allocation-free-behavior/106414/3 "2023-11-19T11:10:54Z")

</div>

Would it be possible to use the same technique from outside a function, to check in the tests for example that a given function signature cannot allocate? Because I can imagine that people don’t always want to have the dynamic dispatch behavior in their actual package but it seems currently you have to apply it to the actual function. You could of course do a wrapper function with the same arguments but it seems tedious maybe

---

<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:** [November 19, 2023, 11:59am UTC](https://discourse.julialang.org/t/ann-alloccheck-jl-static-code-analysis-to-prove-allocation-free-behavior/106414/4 "2023-11-19T11:59:19Z")

</div>

> [@jules](#):
>
> Would it be possible to use the same technique from outside a function, to check in the tests for example that a given function signature cannot allocate?

> **[API · AllocCheck Documentation](https://julialang.github.io/AllocCheck.jl/dev/api/#AllocCheck.check_allocs)**
>
> Documentation for AllocCheck Documentation.

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [November 19, 2023, 12:04pm UTC](https://discourse.julialang.org/t/ann-alloccheck-jl-static-code-analysis-to-prove-allocation-free-behavior/106414/5 "2023-11-19T12:04:09Z")

</div>

> [@jules](#):
>
> Would it be possible to use the same technique from outside a function, to check in the tests for example that a given function signature cannot allocate?

Hard agree on making that the main interface instead of the current method-level annotation. I don’t see myself using this on functions on the critical path, where not getting dynamic dispatch is as important (if not more so) as not getting allocations.

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [November 19, 2023, 12:31pm UTC](https://discourse.julialang.org/t/ann-alloccheck-jl-static-code-analysis-to-prove-allocation-free-behavior/106414/6 "2023-11-19T12:31:20Z")

</div>

> [@jules](#):
>
> Would it be possible to use the same technique from outside a function, to check in the tests for example that a given function signature cannot allocate?

It’s a tool, you can use it however you want. The README example is just one way. There’s two main ways we are starting to make use of the new tool. The first one is to create unit tests that enforce that package code does not allocate in its inner loops. This makes sure that performance doesn’t regress.

But the second way is to ensure builds are safe. When we are building for safety-critical real-time applications, you want to ensure that the real-time loop has certain properties, such as not allocating and thus having no GC pauses. What you can do is add this macro to the binary build so that you have a confirmation that your binary will only build if this property is satisfied, otherwise you get an error before deployment.

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [November 19, 2023, 1:20pm UTC](https://discourse.julialang.org/t/ann-alloccheck-jl-static-code-analysis-to-prove-allocation-free-behavior/106414/7 "2023-11-19T13:20:45Z")

</div>

Ah thanks I missed the functional version reading the docs, focus was on the macro.

---

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [November 19, 2023, 2:15pm UTC](https://discourse.julialang.org/t/ann-alloccheck-jl-static-code-analysis-to-prove-allocation-free-behavior/106414/8 "2023-11-19T14:15:42Z")

</div>

I’m (still) wondering why there isn’t a call site macro (similar to `@code_*`) but only one for method definitions.

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [November 19, 2023, 2:17pm UTC](https://discourse.julialang.org/t/ann-alloccheck-jl-static-code-analysis-to-prove-allocation-free-behavior/106414/9 "2023-11-19T14:17:08Z")

</div>

Open an issue.

---

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [November 19, 2023, 2:43pm UTC](https://discourse.julialang.org/t/ann-alloccheck-jl-static-code-analysis-to-prove-allocation-free-behavior/106414/10 "2023-11-19T14:43:09Z")

</div>

Done: [Call-site macro · Issue #45 · JuliaLang/AllocCheck.jl · GitHub](https://github.com/JuliaLang/AllocCheck.jl/issues/45)

---

<div class="post-metadata">

**Author:** ![sefffal](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sefffal/32/23640_2.png) [@sefffal](https://discourse.julialang.org/u/sefffal)\
**Post date:** [November 19, 2023, 9:28pm UTC](https://discourse.julialang.org/t/ann-alloccheck-jl-static-code-analysis-to-prove-allocation-free-behavior/106414/11 "2023-11-19T21:28:54Z")

</div>

This is really exciting for real time work in Julia!

The last missing piece IMO will be to opt-out functions from GC pauses caused by other threads if the have been proved allocation-free by this macro.

In our current application we have pairs of hard real time and non latency-critical supervisory threads. At the moment, too many allocations on the supervisory thread cause the real time one to pause too.

---

<div class="post-metadata">

**Author:** ![GeorgeGkountouras](https://avatars.discourse-cdn.com/v4/letter/g/77aa72/32.png) [@GeorgeGkountouras](https://discourse.julialang.org/u/GeorgeGkountouras)\
**Post date:** [November 21, 2023, 6:45pm UTC](https://discourse.julialang.org/t/ann-alloccheck-jl-static-code-analysis-to-prove-allocation-free-behavior/106414/12 "2023-11-21T18:45:11Z")

</div>

Hey, this is useful for real-time audio! 📻

Some ideas:

1. Can it be extended to check for locks/files/sleep/sockets? Note that Compare-and-Swap (CAS) and similar paradigms are okay.
2. At the recent Audio Developer Conference, I saw a `Clang`-based [tool](https://github.com/realtime-sanitizer/radsan) that hijacks `malloc` from `libc` and errors at runtime. Since it is not just a static check, it will also work for code that you did not write, but merely linked to.

---

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [November 21, 2023, 6:51pm UTC](https://discourse.julialang.org/t/ann-alloccheck-jl-static-code-analysis-to-prove-allocation-free-behavior/106414/13 "2023-11-21T18:51:45Z")

</div>

Bumper.jl might be interesting to people needing more memory control.

---

<div class="post-metadata">

**Author:** ![ParadaCarleton](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paradacarleton/32/20005_2.png) [@ParadaCarleton](https://discourse.julialang.org/u/ParadaCarleton)\
**Post date:** [November 22, 2023, 8:25pm UTC](https://discourse.julialang.org/t/ann-alloccheck-jl-static-code-analysis-to-prove-allocation-free-behavior/106414/14 "2023-11-22T20:25:54Z")

</div>

Is it possible to integrate this into the VSCode extension somehow, to highlight allocations automatically?

---

<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:** [November 22, 2023, 8:45pm UTC](https://discourse.julialang.org/t/ann-alloccheck-jl-static-code-analysis-to-prove-allocation-free-behavior/106414/15 "2023-11-22T20:45:49Z")

</div>

> [@Sukera](#):
>
> > [@jules](#):
> >
> > Would it be possible to use the same technique from outside a function, to check in the tests for example that a given function signature cannot allocate?
> 
> Hard agree on making that the main interface instead of the current method-level annotation

Also if I’m not gravely misunderstanding something, profiling a call signature seems more properly [“static”](https://en.wikipedia.org/wiki/Static_program_analysis). The macro’ed function needs to be called with runtime inputs to count allocations and does return a value, though the allocations are supposedly searched in the IR itself so the input values and code execution doesn’t sound strictly necessary.

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [November 22, 2023, 10:22pm UTC](https://discourse.julialang.org/t/ann-alloccheck-jl-static-code-analysis-to-prove-allocation-free-behavior/106414/16 "2023-11-22T22:22:32Z")

</div>

> [@ParadaCarleton](#):
>
> Is it possible to integrate this into the VSCode extension somehow, to highlight allocations automatically?

That does sound like a good next step.

---

<div class="post-metadata">

**Author:** ![ericphanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ericphanson/32/215186_2.png) [@ericphanson](https://discourse.julialang.org/u/ericphanson)\
**Post date:** [November 24, 2023, 9:32pm UTC](https://discourse.julialang.org/t/ann-alloccheck-jl-static-code-analysis-to-prove-allocation-free-behavior/106414/17 "2023-11-24T21:32:09Z")

</div>

Do you have any tips for using it with code that uses broadcasting? Since it seems any broadcasted operation has the potential to allocate. For example:

```julia
julia> using AllocCheck

julia> function f!(x, y)
        @. x += y
        end
f! (generic function with 1 method)

julia> x = zeros(10); y = zeros(10);

julia> check_allocs(f!, typeof.((x, y)))
1-element Vector{Any}:
 Allocation of Array in ./array.jl:365
  | copy(a::T) where {T<:Array} = ccall(:jl_array_copy, Ref{T}, (Any,), a)

Stacktrace:
  [1] copy
    @ ./array.jl:365 [inlined]
  [2] unaliascopy
    @ ./abstractarray.jl:1498 [inlined]
  [3] unalias
    @ ./abstractarray.jl:1482 [inlined]
  [4] broadcast_unalias
    @ ./broadcast.jl:947 [inlined]
  [5] preprocess
    @ ./broadcast.jl:954 [inlined]
  [6] preprocess_args
    @ ./broadcast.jl:957 [inlined]
  [7] preprocess_args
    @ ./broadcast.jl:956 [inlined]
  [8] preprocess
    @ ./broadcast.jl:953 [inlined]
  [9] copyto!
    @ ./broadcast.jl:970 [inlined]
 [10] copyto!
    @ ./broadcast.jl:926 [inlined]
 [11] materialize!
    @ ./broadcast.jl:884 [inlined]
 [12] materialize!
    @ ./broadcast.jl:881 [inlined]
 [13] f!(x::Vector{Float64}, y::Vector{Float64})
    @ Main ./REPL[23]:2

```

BTW: thank you! This helped me catch `r .= -g` in a tight loop 😄. Should be `r .= (-1) .* g` to not allocate on the right-hand side.

edit: this seems helpful for ignoring aliasing allocations:

```julia
function check_allocs_ignore_alias(f, args)
    ret = check_allocs(f, args)
    filter!(ret) do s
        all(x -> x.func != :unalias, s.backtrace)
    end
    return ret
end

```

---

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [November 25, 2023, 6:22am UTC](https://discourse.julialang.org/t/ann-alloccheck-jl-static-code-analysis-to-prove-allocation-free-behavior/106414/18 "2023-11-25T06:22:39Z")

</div>

I guess the proper solution here would be to tell the compiler that there is no aliasing in the first place. Something like `restrict` from C would be nice.

UPDATE:

Out of curiosity, I tried this but unfortunately there is still a potential allocation reported (maybe the hint is only lexically scoped):

```julia
julia> using Base.Experimental: @aliasscope, Const

julia> function f_noalias!(x, y)
           @aliasscope begin
               @. x += Const(y)
           end
       end
f_noalias! (generic function with 1 method)

julia> check_allocs(f_noalias!, typeof.((x, y)))
1-element Vector{Any}:
 Allocation of Array in ./array.jl:409
  | copy(a::T) where {T<:Array} = ccall(:jl_array_copy, Ref{T}, (Any,), a)

Stacktrace:
  [1] copy
    @ ./array.jl:409 [inlined]
  [2] unaliascopy
    @ ./abstractarray.jl:1490 [inlined]
  [3] unalias
    @ ./abstractarray.jl:1474 [inlined]
  [4] broadcast_unalias
    @ ./broadcast.jl:977 [inlined]
  [5] preprocess
    @ ./broadcast.jl:984 [inlined]
  [6] preprocess_args
    @ ./broadcast.jl:987 [inlined]
  [7] preprocess
    @ ./broadcast.jl:983 [inlined]
  [8] preprocess_args
    @ ./broadcast.jl:987 [inlined]
  [9] preprocess_args
    @ ./broadcast.jl:986 [inlined]
 [10] preprocess
    @ ./broadcast.jl:983 [inlined]
 [11] copyto!
    @ ./broadcast.jl:1000 [inlined]
 [12] copyto!
    @ ./broadcast.jl:956 [inlined]
 [13] materialize!
    @ ./broadcast.jl:914 [inlined]
 [14] materialize!
    @ ./broadcast.jl:911 [inlined]
 [15] macro expansion
    @ ./REPL[34]:3 [inlined]
 [16] macro expansion
    @ ./experimental.jl:49 [inlined]
 [17] f_noalias!(x::Vector{Float64}, y::Vector{Float64})
    @ Main ./REPL[34]:2

```

Related issues/PRs: julia#8087, julia#19658, julia#31018

---

<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:** [November 25, 2023, 2:27pm UTC](https://discourse.julialang.org/t/ann-alloccheck-jl-static-code-analysis-to-prove-allocation-free-behavior/106414/19 "2023-11-25T14:27:26Z")

</div>

> [@carstenbauer](#):
>
> ```julia
> julia> using Base.Experimental: @aliasscope, Const
> 
> julia> function f_noalias!(x, y)
> @aliasscope begin
> @. x += Const(y)
> end
> end
> f_noalias! (generic function with 1 method)
> 
> ```

FTR, the equivalent code with my package UnsafeAssume.jl might look something like this:

```julia
using UnsafeAssume

function f_noalias!(x, y)
  @inline begin
    unsafe_assume_condition(!Base.mightalias(x, y))
    @. x += y
  end
end

```

But it’s no better at eliminating the allocations. EDIT: there is no allocating code generated, it was a bug with AllocCheck for nightly Julia v1.11.

EDIT: another option would be to use LLVM’s `assume` intrinsic to mark a pointer as `noalias`, but this would be more complicated to use, because loading `Ptr` then requires weird stuff like `GC.@preserve`.

I notice that Julia for some reason doesn’t seem to be able to infer _any_ effects for `f!(x, y) = @. x += y`:

```julia-repl
julia> Base.infer_effects(f!, Tuple{Vector{Int}, Vector{Int}})
(!c,!e,!n,!t,!s,!m,!u)′

```

So there may be other issues at play here, I think.

---

<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:** [November 25, 2023, 3:40pm UTC](https://discourse.julialang.org/t/ann-alloccheck-jl-static-code-analysis-to-prove-allocation-free-behavior/106414/20 "2023-11-25T15:40:34Z")

</div>

> [@nsajko](#):
>
> `unsafe_assume_condition(!Base.mightalias(x, y))`

~~On second thought, I don’t think this would work. For the call to have an effect, LLVM must be able to infer that `x` and `y` don’t alias from the fact that `Base.mightalias(x, y)` is `false`, but I’m not sure that’s even possible.~~

[Next page](https://discourse.julialang.org/t/ann-alloccheck-jl-static-code-analysis-to-prove-allocation-free-behavior/106414.md?page=2)
