repo: https://github.com/artemsolod/ArenaPirate.jl
This package redefines Memory{T}(::UndefInitializer, m::Int64)
(hence “pirate” in the name) and provides an @arena
macro for marking sections of code to be eligible for arena allocation. Large enough allocations of Memory{T}
with isbitstype(T)
get arena allocated provided arena has sufficient remaining capacity. Standard julia allocation is used as fallback. I’ve been playing with this for a couple of weeks and found it quite useful in GC-bound workloads.
Here is a comparison of timings for calling f(x) = median(x)
vs f_arena(x) = @arena f(x)
on a 10 mln element vector and repeated calls (32 runs: single and multithreaded on 8 threads – see examples/medians.jl
). Note that the Statistics.median
function is allocating and is not @arena
-aware.
____ Built-in allocator benchmarks:
0.154144 seconds (18 allocations: 78.262 MiB, 16.38% gc time) # single call
4.363108 seconds (298 allocations: 2.446 GiB, 6.95% gc time) # 32 repeated calls
1.384049 seconds (340 allocations: 2.446 GiB, 25.96% gc time) # 32 calls using Threads.@threads
____ Arena benchmarks:
0.072805 seconds (55 allocations: 2.000 KiB) # single call (@arena)
2.346896 seconds (747 allocations: 17.250 KiB) # 32 repeated calls (@arena)
0.413609 seconds (810 allocations: 21.562 KiB) # 32 calls using Threads.@threads (@arena)
I would like to hear your feedback: ideas for performance improvements, bug reports, interface improvements. And especially how it can be extended, i.e. what are all arena-allocatable things?