Skip to content

HTTPS clone URL

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
Neeraj Singh 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
View
@@ -135,14 +135,13 @@ def extending(*modules, &block)
end
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(Arel::SqlLiteral.new(order))
+ except(:order).order(Arel::SqlLiteral.new(order))
end
def arel
@@ -283,15 +282,15 @@ def apply_modules(modules)
end
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')
else
- s.concat(' DESC')
+ s + ' DESC'
end
- }.join(',')
+ }
end
def array_of_strings?(o)

12 comments on commit fbd1d30

Carlos Antonio da Silva

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

Neeraj Singh
Collaborator

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.

Carlos Antonio da Silva

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?

Neeraj Singh
Collaborator

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

Carlos Antonio da Silva

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

thedarkone

How about doing "Lazy gsub!": http://gist.github.com/599605?

Neeraj Singh
Collaborator

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.

Carlos Antonio da Silva

Yeah agreed, nice one!

Neeraj Singh
Collaborator

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! .

thedarkone

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

lsylvester

I have run a benchmark at http://gist.github.com/600385

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)
Neeraj Singh
Collaborator

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.