AllocCheck.check_allocsMethod
check_allocs(func, types; ignore_throw=true)

Compiles the given function and types to LLVM IR and checks for allocations.

Returns a vector of AllocationSite, DynamicDispatch, and AllocatingRuntimeCall

Warning

The Julia language/compiler does not guarantee that this result is stable across Julia invocations.

If you rely on allocation-free code for safety/correctness, it is not sufficient to verify check_allocs in test code and expect that the corresponding call in production will not allocate at runtime.

For this case, you must use @check_allocs instead.

Example

julia> function foo(x::Int, y::Int)
           z = x + y
           return z
       end
foo (generic function with 1 method)

julia> allocs = check_allocs(foo, (Int, Int))
AllocCheck.AllocationSite[]
AllocCheck.classify_runtime_fnMethod
classify_runtime_fn(name)

A :dispatch function is responsible for a "dynamic dispatch" to an unknown Julia function.

An :alloc functions is used by codegen to lower allocations for mutable structs, arrays, and other Julia objects.

A :runtime function is any function used by the runtime which does not explicitly perform allocation, but which might allocate to get its job done (e.g. jl_subtype).

AllocCheck.compile_callableMethod
compile_callable(f, tt=Tuple{}; kwargs...)

Low-level interface to compile a function invocation for the provided function and tuple of argument types using the naive JuliaOJIT() pipeline.

The output of this function is automatically cached, so that new code will be generated automatically and checked for allocations whenever the function changes or when different types or keyword arguments are provided.

AllocCheck.find_allocs!Method

Find all static allocation sites in the provided LLVM IR.

This function modifies the LLVM module in-place, effectively trashing it.

AllocCheck.forward_args!Method

Takes a function definition and returns the expressions needed to forward the arguments to an inner function.

For example function foo(a, ::Int, c...; x, y=1, z...) will

  1. modify the function to gensym() nameless arguments
  2. return (:a, gensym(), :(c...)), (:x, :y, :(z...)))
AllocCheck.rename_call!Method

Resolve the callee of a call embedded in Julia-constructed LLVM IR and replace it with a new locally-declared function that has the resolved name as its identifier.

AllocCheck.@check_allocsMacro
@check_allocs ignore_throw=true (function def)

Wraps the provided function definition so that all calls to it will be automatically checked for allocations.

If the check fails, an AllocCheckFailure exception is thrown containing the detailed failures, including the backtrace for each defect.

Note: All calls to the wrapped function are effectively a dynamic dispatch, which means they are type-unstable and may allocate memory at function entry. @check_allocs only guarantees the absence of allocations after the function has started running.

Example

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

julia> multiply(1.5, 3.5) # no allocations for Float64
5.25

julia> multiply(rand(3,3), rand(3,3)) # matmul needs to allocate the result
ERROR: @check_allocs function contains 1 allocations.

Stacktrace:
 [1] macro expansion
   @ ~/repos/AllocCheck/src/macro.jl:134 [inlined]
 [2] multiply(x::Matrix{Float64}, y::Matrix{Float64})
   @ Main ./REPL[2]:133
 [3] top-level scope
   @ REPL[5]:1