Why would I ever use deepcopy?

question

#1

deepcopy is generally slower for arrays than creating a new array and copying the data from the old array, so why would I every use it then? deepcopy creates an ObjectIdDict internally which probably causes the main performance overhead.

julia> using BenchmarkTools

julia> f(x) = deepcopy(x)
f (generic function with 1 method)

julia> function g(x::Array{T}) where T
           y = Array{T}(undef, length(x))
           copyto!(y, x)
       end
g (generic function with 2 methods)

julia> x = collect(1:100);

julia> @benchmark f($x)
BenchmarkTools.Trial: 
  memory estimate:  1.30 KiB
  allocs estimate:  3
  --------------
  minimum time:     201.290 ns (0.00% GC)
  median time:      220.049 ns (0.00% GC)
  mean time:        269.109 ns (13.64% GC)
  maximum time:     63.888 μs (99.18% GC)
  --------------
  samples:          10000
  evals/sample:     606

julia> @benchmark g($x)
BenchmarkTools.Trial: 
  memory estimate:  896 bytes
  allocs estimate:  1
  --------------
  minimum time:     106.996 ns (0.00% GC)
  median time:      124.724 ns (0.00% GC)
  mean time:        150.505 ns (13.92% GC)
  maximum time:     41.561 μs (99.36% GC)
  --------------
  samples:          10000
  evals/sample:     935

@yuyichao said on github :

To put it simply though, if you don’t know why you should use deepcopy, that’s likely not the function you want. It’s not a function to use in most cases.

For me the main usage is to copy an array, and as it is the simplest way to do so provided by the language, I also expected it to be the fastest. I did not expect deepcopy to be the performance bottleneck which caused some confusion.

EDIT: added note about ObjectIdDict
EDIT: added response to @yuyichao’s comment on github


#2

If the elements of a container are themselves mutable containers, and you want to avoid shared structure. Eg an array of arrays, etc.


#3

so it is recursive?


#4

apparently :wink::

help?> deepcopy
search: deepcopy

  deepcopy(x)

  Create a deep copy of x: everything is copied recursively

#5

See the doc.

Create a deep copy of x: everything is copied recursively, resulting in a fully independent object. For example, deep-copying an array produces a new array whose elements are deep copies of the original elements. Calling deepcopy on an object should generally have the same effect as serializing and then deserializing it.

No, not even close, I said that

Yes it is, and it has to be slower than copy. If you need copy (i.e. g) instead of deepcopy (i.e. f), you should use that instead.

deepcopy is used when you generally want to create an object tree that’s completely independent on the original one, say if you are going to mutate one of the copy but want to be able to restart later from the same point, for caching/testing purpose etc. If you have some more specific requirements for the copy, you should be better off writing one one you own (e.g. one that only copy one or two levels).

Again, see the doc…


#6

ok, I was somewhat confused on the differences between =, copy, and deepcopy. Thanks for clearing that up and answering my stupid question :wink:!