Closed edbond closed 2 years ago
ruby 2.2.1p85 (2015-02-26 revision 49769) [x86_64-linux]
Calculating -------------------------------------
!Array#empty? 143.635k i/100ms
Array#any? 134.023k i/100ms
-------------------------------------------------
!Array#empty? 7.107M (± 1.9%) i/s - 35.621M
Array#any? 6.760M (± 1.9%) i/s - 33.908M
Comparison:
!Array#empty?: 7107124.9 i/s
Array#any?: 6760372.4 i/s - 1.05x slower
The methods aren't equivalent, it's insane to compare them:
ARRAY = Array.new(100_000, false).push(true)
# Calculating -------------------------------------
# !Array#empty? 206.932k i/100ms
# Array#any? 2.062k i/100ms
# -------------------------------------------------
# !Array#empty? 8.893M (± 4.2%) i/s - 44.490M
# Array#any? 21.150k (± 1.3%) i/s - 107.224k
# Comparison:
# !Array#empty?: 8893115.8 i/s
# Array#any?: 21149.7 i/s - 420.48x slower
One checks if an array is empty, the other iterates an enumerable looking for a truthy value (or given a block, any truthy value the block returns).
Instead of Array#any?
why not compare it with array.size == 0
, that seems a bit more fair
@IceDragon200 #empty?
is the same as #size == 0
empty?
static VALUE
rb_ary_empty_p(VALUE ary)
{
if (RARRAY_LEN(ary) == 0)
return Qtrue;
return Qfalse;
}
size
static VALUE
rb_ary_length(VALUE ary)
{
long len = RARRAY_LEN(ary);
return LONG2NUM(len);
}
@edbond What I was aiming for was the execution overhead in ruby for doing an Array#size
+ Integer#==
vs using Array#empty?
. Think about folks coming from JS who are used to [].length
for checking if an array is empty
FWIW, #any?
vs ! + #empty?
was big news to me and a couple coworkers when we heard it (moreover, the number of copies it makes was a bit eye-opening)
require 'benchmark/ips'
ARRAY = [*1..1000]
def fastest
!ARRAY.empty?
end
def faster
ARRAY.size != 0
end
def fast
!ARRAY.size.zero?
end
def slow
!!ARRAY.size.nonzero?
end
def slower
ARRAY.any? { true }
end
def slowest
ARRAY != []
end
p !ARRAY.size.zero?
p !ARRAY.empty?
p ARRAY.size != 0
p !!ARRAY.size.nonzero?
p ARRAY.any? { true }
p ARRAY != []
Benchmark.ips do |bm|
bm.report('!ary.empty?') { fastest }
bm.report('ary.size != 0') { faster }
bm.report('!ary.size.zero?') { fast }
bm.report('!!ary.size.nonzero?') { slow }
bm.report('ary.any? { true }') { slower }
bm.report('ary != []') { slowest }
bm.compare!
end
On my machine:
true
true
true
true
true
true
Calculating -------------------------------------
!ary.empty? 196.739k i/100ms
ary.size != 0 188.360k i/100ms
!ary.size.zero? 193.306k i/100ms
!!ary.size.nonzero? 174.423k i/100ms
ary.any? { true } 169.659k i/100ms
ary != [] 164.195k i/100ms
-------------------------------------------------
!ary.empty? 8.719M (± 3.5%) i/s - 43.676M
ary.size != 0 8.615M (± 1.8%) i/s - 43.134M
!ary.size.zero? 8.127M (± 1.8%) i/s - 40.788M
!!ary.size.nonzero? 6.521M (± 1.4%) i/s - 32.617M
ary.any? { true } 5.428M (± 1.5%) i/s - 27.145M
ary != [] 5.423M (± 3.2%) i/s - 27.092M
Comparison:
!ary.empty?: 8719246.6 i/s
ary.size != 0: 8614787.7 i/s - 1.01x slower
!ary.size.zero?: 8126586.6 i/s - 1.07x slower
!!ary.size.nonzero?: 6520599.1 i/s - 1.34x slower
ary.any? { true }: 5428154.2 i/s - 1.61x slower
ary != []: 5423254.4 i/s - 1.61x slower
But I don't think it's worth comparing !ary.empty?
to ary.size != 0
as no one would pick the latter. Same goes for ary.any?
which is not an obvious choice anyway.
Hi. Pardon me as I am helping @JuanitoFatas to clear the PRs.
I would agree with @Arcovion in this case and it seems strange to make this comparison. :kissing_heart:
Difference for 2.1.4 is much bigger.