Skip to content


Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Three performance improvements:

* for simple cases like User.last and User.order('name desc').last no need to perform Array#join operation.

* Instead of performing String#blank? do Array#empty?

* no need to create variable relation
  • Loading branch information...
commit fbd1d306b95cc2efb6422e12d26d5818a3a42343 1 parent e3d6434
@neerajdotname neerajdotname authored tenderlove committed
Showing with 9 additions and 10 deletions.
  1. +9 −10 activerecord/lib/active_record/relation/query_methods.rb
19 activerecord/lib/active_record/relation/query_methods.rb
@@ -135,14 +135,13 @@ def extending(*modules, &block)
def reverse_order
- order_clause = arel.order_clauses.join(', ')
- relation = except(:order)
+ order_clause = arel.order_clauses
- order = order_clause.blank? ?
+ order = order_clause.empty? ?
"#{@klass.table_name}.#{@klass.primary_key} DESC" :
- reverse_sql_order(order_clause)
+ reverse_sql_order(order_clause).join(', ')
- relation.order(
+ except(:order).order(
def arel
@@ -283,15 +282,15 @@ def apply_modules(modules)
def reverse_sql_order(order_query)
- order_query.split(',').each { |s|
+ order_query.join(', ').split(',').collect { |s|
if s.match(/\s(asc|ASC)$/)
- s.gsub!(/\s(asc|ASC)$/, ' DESC')
+ s.gsub(/\s(asc|ASC)$/, ' DESC')
elsif s.match(/\s(desc|DESC)$/)
- s.gsub!(/\s(desc|DESC)$/, ' ASC')
+ s.gsub(/\s(desc|DESC)$/, ' ASC')
- s.concat(' DESC')
+ s + ' DESC'
- }.join(',')
+ }
def array_of_strings?(o)

12 comments on commit fbd1d30


Just a question, why removing gsub! and concat in reverse_sql_order?


so that code like "created_at, updated_at" works with User.last. Note that the whole thing is a string. Hence we need to split by a comma.


Yeah sure Neeraj, but I believe it'd be possible to return the s variable inside the collect, keeping the methods that changes the actual string, would not?


Not sure if I am following you exactly. Can you post a gist or something?


Sure, here we go:
I also thought about some other possibilities to see what you think (didn't actually tested it), please take a look.


How about doing "Lazy gsub!":


I think I like the "lazy gsub!" . In all other cases first a regex check is being done and then gsub is being invoked. The "lazy gsub!" totally removes the need to do any regex check.


Yeah agreed, nice one!


Although the underlying assumption here is that gusb! is faster than regex. Unless there is benchmarking data I don't really know. May be someone from ruby core ( Aaron Patterson) might be able to tell which one is faster.

If regex turns out to be faster than gsub! then we should stick with regex approach. Otherwise switch to gsub! .


I'd probably guess lazy gsub! to be slightly faster. I've also updated the gist ( with a slightly better regexps, so somebody should run a bench and whip up a patch.


I have run a benchmark at

It looks like the lazy gsub! is faster.

          user     system      total        real
  orig:   1.660000   0.040000   1.700000 (  1.689658)
  mod1:   1.650000   0.030000   1.680000 (  1.693604)
  mod2:   1.370000   0.030000   1.400000 (  1.395524)
  mod3:   1.340000   0.020000   1.360000 (  1.358895)
  lazy:   0.930000   0.030000   0.960000 (  0.954206)

I'm blown away by the result. That's significant perf improvement.

Please sign in to comment.
Something went wrong with that request. Please try again.