We have learnt a tip for writing faster ruby code and profiling ruby in last past. Today we will see a few more tips to write faster ruby code.

Tip #2: Avoid Temporary Objects:
Consider following ruby code, how can we make it fast?

#!/usr/bin/env ruby
require 'benchmark'

a = ""
1_000_00.times { a += "." }

If you notice the main working line “a += “.” , this line will expand as

a = a + “.”

Which means that every time we are doing this operation, we are creating a temporary objects with value (a + “.”) and then assigning it back to a. The creation of this temporary variable is actually costing us most of the time and space. If we can avoid the use of this temporary variable, we can make things faster. Consider the following:

#!/usr/bin/env ruby
require 'benchmark'

a = ""
1_000_00.times { a << "." }

Above code is doing the same thing as we have done earlier but runs much faster. If we profile it using benchmark or ruby-prof, we can see the benefits of avoiding temporary objects. Below are the benchmark results of above 2 approaches, notice the 2nd approach is almost 100 times faster :

Rehearsal ---------------------------------------
+= 2.740000 0.460000 3.200000 ( 3.250396)
<< 0.040000 0.000000 0.040000 ( 0.037068)
------------------------------ total: 3.240000sec

user system total real
+= 2.760000 0.510000 3.270000 ( 3.352737)
<< 0.040000 0.000000 0.040000 ( 0.036535)

Tip #3: Use Destructive functions:
Consider following functions calls, can we make it faster?

“akashagrawal”.gsub
“akashagrawal”.sub
“akash” + “agrawal”
[1, 2].collect
[1, 2].compact
[1, 2].uniq
[1 , [2, 3]].flatten
[1] + [2]

Each and every line in above code creates a temporary object and then assigning the same to that object. If we use the corresponding destructive version of above (given below), we can save a lot of time.

“akashagrawal”.gsub!
“akashagrawal”.sub!
“akash” << “agrawal”
[1, 2].collect!
[1, 2].compact!
[1, 2].uniq!
[1 , [2, 3]].flatten!
[1].concat[2]

I am leaving the exercise of benchmarking the usage of destructive vs non-destructive function to readers.

PS: Don’t overuse destructive functions, as “Premature optimization is the root of all evil.

Subscribe - To get an automatic feed of all future posts subscribe here, or to receive them via email go here and enter your email address in the box. You can also like us on facebook and follow me on Twitter @akashag1001.