# Allocations in a copy! construct

Consider the following variations of in-place copying:

``````lower = 1.:3
upper = 12.:16

function a()
points = zeros(100)
allocs = @allocated copy!(points, [lower[1:end-1]; upper[1:end-1]])
println("case a: \$allocs bytes")
resize!(points, length(lower)+length(upper)-2)
end

function b()
points = zeros(100)
allocs = @allocated begin
copy!(points, lower[1:end-1])
copy!(points, length(lower), upper[1:end-1])
end
println("case b: \$allocs bytes")
resize!(points, length(lower)+length(upper)-2)
end

function c()
points = zeros(100)
allocs = @allocated begin
copy!(points, @view(lower[1:end-1]))
copy!(points, length(lower), @view(upper[1:end-1]))
end
println("case c: \$allocs bytes")
resize!(points, length(lower)+length(upper)-2)
end
``````

The result that i get (in the second run), is:

``````julia> a(); b(); c();
case a: 320 bytes
case b: 192 bytes
case c: 1728 bytes
``````
• In case a, does `[lower[1:end-1]; upper[1:end-1]]` as a second argument to `copy!` create a temporary vector, while in case b it doesnâ€™t, explaining that they differ roughly in twice as many allocations?
• For case c, why does it allocate that much, shouldnâ€™t it be the same as case b?

This is the global scope problems. If you declare lower and upper as const, only a() allocates.

1 Like

Huh, i thought that enclosing the `@allocated` macros inside the function was enough. Thanks for the tip!!

Now cases b and c allocate exactly 0 bytes, now i see thatâ€™s the behavior to be expected there.

Yes, global variables are evil (hopefully theyâ€™ll get optimized a bit at some point). Thereâ€™s a trick though : it only does not allocate because lower and upper are ranges. If they are arrays (with collect() in front of the ranges) then b and c allocate. b has to allocate because indexing is a copy, the fact that c allocates is a bug (I think itâ€™s on the devs radar, but low priority)

1 Like

Ok, interesting. Then `copy!(points, lower[1:end-1])` didnâ€™t create temporaries just because `lower` is a lazy array, i overlooked that. Trying with arrays behaves as you say, case c allocating less than b (but not exactly zero).