We should measure! I'm going to hypothesize that [-1] and #last will be slightly faster than [len - 1] due to having one less method call.
require 'benchmark/ips'
arr = (1..100).to_a
Benchmark.ips do |x|
x.report("last") { arr.last }
x.report("-1") { arr[-1] }
x.report("len - 1") { arr[arr.length - 1] }
end
Results:
$ ruby -v
ruby 2.0.0p353 (2013-11-22 revision 43784) [x86_64-linux]
$ ruby bench.rb
Calculating -------------------------------------
last 127496 i/100ms
-1 133726 i/100ms
len - 1 127050 i/100ms
-------------------------------------------------
last 6528395.1 (±0.4%) i/s - 32638976 in 4.999622s
-1 7802109.3 (±1.7%) i/s - 39047992 in 5.006745s
len - 1 7046531.5 (±0.3%) i/s - 35319900 in 5.012415s
$ ruby -v
ruby 2.1.1p76 (2014-02-24 revision 45161) [x86_64-linux]
$ ruby bench.rb
Calculating -------------------------------------
last 130228 i/100ms
-1 129587 i/100ms
len - 1 126966 i/100ms
-------------------------------------------------
last 6787424.0 (±0.2%) i/s - 33989508 in 5.007732s
-1 7915058.4 (±0.6%) i/s - 39653622 in 5.010079s
len - 1 7126295.0 (±0.5%) i/s - 35677446 in 5.006563s
$ ruby -v
jruby 1.7.18 (1.9.3p551) 2014-12-22 625381c on
OpenJDK 64-Bit Server VM 1.8.0_25-b18 +jit [linux-amd64]
$ ruby bench.rb
Calculating -------------------------------------
last 212.085k i/100ms
-1 226.292k i/100ms
len - 1 226.245k i/100ms
-------------------------------------------------
last 13.935M (± 4.4%) i/s - 69.352M
-1 13.696M (± 5.1%) i/s - 68.340M
len - 1 11.732M (± 3.2%) i/s - 58.597M
-1 is very slightly faster under ruby 2.0.0 and 2.1.1, #last is fastest under JRuby (which is itself almost 2x faster than MRI, probably because of that delicious JIT).
In all cases, it runs really fast and it's probably one of the last things you should be trying to optimize.