What's the fastest way to sum up an Array in Ruby?

What's the fastest way to sum up an Array in Ruby?

Update: I created a YouTube short covering this, updated for Ruby 3.2. Take a look!

Let's say you have an array of numbers. How do you get the sum of them?

One way is to iterate through the list and start adding them up one by one. In Ruby, you could write this as array.inject(&:+). Per the Ruby documentation,

[#inject] Combines all elements of enum by applying a binary operation, specified by a block or a symbol that names a method or operator.

So essentially, work your way iteratively through the list you have provided and perform the specified action on each one with the previous value. Seems logical enough.

Inject vs Sum

Another alternative to this is to call Enumerable#sum instead. At the very least, this is at least much more readable, and there's something to be said for that.

Let's benchmark this scenario. To do this, we're going to generate 50,000 lists, each with 10,000 integers. We will then run the inject approach first, then the sum approach second.

Building arrays...
Running benchmarks...
             user     system      total        real
Inject: 24.530000   0.000000  24.530000 ( 24.535001)
Sum:     0.650000   0.000000   0.650000 (  0.655893)
#inject vs #sum

Ranges

Let's look at a variation on this. What happens if you are working with a Range, rather than an Array?

Ranges don't actually contain a list of every single number in between them. Instead, they track the starting and ending numbers. There is a simple formula for this:

(range.max - range.min + 1) * (range.max + range.min) / 2

Let's update our benchmark to check the performance of range sums. While it's more random, this takes the first integer in each list and builds a range from that.

Building arrays...
Running benchmarks...
             user     system      total        real
Inject: 25.490000   0.010000  25.500000 ( 25.491691)
Sum:     0.660000   0.000000   0.660000 (  0.660099)
Range:   0.010000   0.000000   0.010000 (  0.016203)

GitHub source code here.