Performance of findfirst in 0.7


#1

Hi All,

The performance of findfirst(A, value) has significantly been affected in 0.7. It’s understandable that the method is deprecated. But changing the functionality in a manner that performance is substantially affected can be a significant issue for applications where it has been used. Here are some numbers from 0.6 and 0.7 for comparison.

0.6:

julia> a = fill(1, 2048); @time findfirst(a, 5)
  0.000004 seconds (4 allocations: 160 bytes)
0

0.7:

julia> a = fill(1, 2048); @time findfirst(a, 4)
┌ Warning: `findfirst(A, v)` is deprecated, use `coalesce(findfirst(isequal(v), A), 0)` instead.
│   caller = top-level scope at util.jl:156
└ @ Core util.jl:156
  0.002726 seconds (372 allocations: 23.250 KiB)
0

The sheer number of allocations are good enough indication that there is lots more happening within the method now in 0.7. Because of this some code is almost crawling in their 0.7 implementation which were fairly fast in 0.6.

Please note that the measurements are after several runs so initial start up overheads have been eliminated already.

regards,

Sambit


#2

Did you miss the deprecation warning?

Using BenchmarkTools.jl:

0.6:

julia> @btime findfirst($a, 4)
  1.368 μs (0 allocations: 0 bytes)
0

0.7:

julia> @btime findfirst(isequal(4), $a) # returns `nothing`
  1.626 μs (0 allocations: 0 bytes)

#3

@kristoffer.carlsson Your suggested code cannot be run with 0.6 as Fix2 was not defined in 0.6. Deprecation should mean the functionality will be removed not something that was working will not perform. Otherwise one has to keep on implementing 2 versions in the code till 0.7 is released.


#4

The idea is to use Compat.jl and only use the 0.7 version from now on. i.e. your code above should look like

using Compat

a = fill(1, 2048)
findfirst(isequal(4), a)

Alternatively, if you don’t want to use Fix2 you can just do

findfirst(x -> x == 4, a)

#5

The kind people who write


already did this for you.


#6

By the way, when did we get currying? I didn’t think any of this was going to happen until after 1.0? (When I thought we would get general currying with _.) It looks like there are some functions in Base that just have explicit currying methods, but I can’t see which. Is there a link to the issue?


#7

#8

@ExpandingMan using compat fixes the performance issue. Thanks.


#9

Quite surprising, one looks at isequal(4) and has no idea what this could be :frowning:

(but, ok - thanks for the link - read the discussion now in #26436 (don’t have an opinion))


#10

It reads pretty cleanly no? findfirst(isequalto(4), a) – find the first (element) that is equal to 4 in a.


#11

Not sure. One has to think the ‘to’ part - the function is called ‘isequal’ and not ‘isequalto’ - but then yes, it reads pretty cleanly. If one just enters isequal(4) into the console to find out what this could mean, it won’t work. - Will try to read it as a sentence, this is a good hint.