I have some complicated code that uses a combination of reshape() and view(), and in my complicated code both reshape() and view() allocates. Trying to reduce my code to an MRE, I came up with this:
function profile_allocs()
x = randn(6)
Profile.Allocs.clear()
Profile.Allocs.@profile sample_rate=1.0 begin
x = reshape(x, (3,2))
sum(view(x, :))
end
Profile.Allocs.print()
end
On 1.11.9, this allocates:
julia> profile_allocs()
Overhead ╎ [+additional indent] Count File:Line; Function
=========================================================
# ...
╎ ╎ ╎ 32 REPL[2]:4; profile_allocs()
╎ ╎ ╎ 32 @Profile/src/Allocs.jl:82; macro expansion
╎ ╎ ╎ 32 REPL[2]:6; macro expansion
╎ ╎ ╎ ╎ 32 @Base/subarray.jl:216; view
╎ ╎ ╎ ╎ 32 @Base/subarray.jl:156; _maybe_reshape_parent
╎ ╎ ╎ ╎ 32 @Base/reshapedarray.jl:152; reshape
╎ ╎ ╎ ╎ 32 @Base/reshapedarray.jl:121; reshape
32╎ ╎ ╎ ╎ 32 @Base/reshapedarray.jl:60; reshape
Total snapshots: 1
Total bytes: 32
On 1.12.5, this does not allocate:
julia> profile_allocs()
Overhead ╎ [+additional indent] Count File:Line Function
=========================================================
┌ Warning: There were no samples collected.
│ Run your program longer (perhaps by running it multiple times),
│ or adjust the frequency of samples to record every event with
│ the `sample_rate=1.0` kwarg.
└ @ Profile.Allocs ~/.julia/juliaup/julia-1.12.5+0.aarch64.apple.darwin14/Julia-1.12.app/Contents/Resources/julia/share/julia/stdlib/v1.12/Profile/src/Allocs.jl:226
I guess my primary objective here is trying to understand why v1.11 allocates, but anything that sheds some light on Julia’s current allocation behaviour will probably be useful.