Is `empty!` O(1)?

The doc page says that

empty! is nearly costless (and O(1)) for types that support this kind of preallocation.

But the code of empty! and _deleteend! show that it’s in O(n) complexity. The _unsetindex! in iteration body seems to do some gc reference counting job. However, is this necessary for a primitive type like Float64?

I also did some simple benchmark:

julia> a = ones(100000); @time empty!(a);

0.000010 seconds

julia> a = ones(1000000); @time empty!(a);

0.000042 seconds

julia> a = ones(10000000); @time empty!(a);

0.000516 seconds

julia> a = ones(100000000); @time empty!(a);

0.003783 seconds

It does look like in O(n) (linear time complexity).

I consider that the only thing empty!(::Vector{Float64}) should do is to reset the “end pointer” to the first element and the length to 0, which is O(1).

Did I miss something? How to reuse a Vector efficiently?

2 Likes

this is a performance bug in 1.11. the fix has been merged into 1.12 already and I think it is getting backported.

4 Likes

see make `_unsetindex` fast for isbits eltype by oscardssmith · Pull Request #56364 · JuliaLang/julia · GitHub

9 Likes

Okay… I never thought it would be a bug… This once led me into self-doubt.

Trust your reasoning, especially if you have hard data that supports it. :slight_smile:

3 Likes