|
onfirm this fix removes that huge number of allocations, it is a huge perf boost for AR. |
|
|
|
A very big reason for the excessive allocations is us, for example we run: |
|
|
|
SELECT "topics".* FROM "topics" WHERE ("topics"."deleted_at" IS NULL) AND (topics.archetype <> 'private_message') ORDER BY CASE WHEN topics.category_id IS NULL and topics.pinned THEN 0 ELSE 1 END, topics.bumped_at DESC LIMIT 30 |
|
We are not limiting down to the actual columns we need, this table has 38 columns, so that means the pg gem is allocating at least double the amount of strings we need. |
|
|
|
The natural thing is to add a .select there, but my concern is that if we forget a column the failure mode is very problematic, stuff will not "explode" it will fail silently pretending the missing columns are nil. I wonder if we should add some special mode in dev to assist here. Regardless, we will fix this. |
|
|
|
Additionally, we have an N+1 query hanging off category. |
|
|
|
I think I will add a mode to MiniProfiler that allows you to see object creation count per query, that will allow people to attack the biggest offenders. |
|
|
|
The very frustrating thing about this topic table is that only 2 out of the 38 columns are actually strings. |
|
|
|
I profiled the simple: |
|
|
|
(ran it twice before in production to ensure it was warmed up), and got: |
|
|
|
Topic.limit(30).to_a |
|
|
|
Amount of string allocations still feels excessive (even after the patch - I patched local) |
|
|
|
File / Line Number / Allocations. |
|
------------------------------------- |
|
/gems/activerecord-3.2.12/lib/active_record/connection_adapters/abstract_adapter.rb 276 1 |
|
/gems/activerecord-3.2.12/lib/active_record/log_subscriber.rb 4 1 |
|
/gems/activerecord-3.2.12/lib/active_record/log_subscriber.rb 8 1 |
|
/gems/activerecord-3.2.12/lib/active_record/querying.rb 38 1 |
|
/gems/activerecord-3.2.12/lib/active_record/relation/spawn_methods.rb 53 1 |
|
/gems/activerecord-3.2.12/lib/active_record/scoping/default.rb 119 1 |
|
/gems/arel-3.0.2/lib/arel.rb 43 1 |
|
/gems/arel-3.0.2/lib/arel/visitors/to_sql.rb 126 1 |
|
/gems/arel-3.0.2/lib/arel/visitors/to_sql.rb 131 1 |
|
/gems/arel-3.0.2/lib/arel/visitors/to_sql.rb 135 1 |
|
/gems/arel-3.0.2/lib/arel/visitors/to_sql.rb 139 1 |
|
/gems/arel-3.0.2/lib/arel/visitors/to_sql.rb 192 1 |
|
/gems/arel-3.0.2/lib/arel/visitors/to_sql.rb 200 1 |
|
/gems/arel-3.0.2/lib/arel/visitors/to_sql.rb 283 1 |
|
/gems/arel-3.0.2/lib/arel/visitors/to_sql.rb 339 1 |
|
test.rb 4 1 |
|
test.rb 7 1 |
|
/gems/activerecord-3.2.12/lib/active_record/relation/query_methods.rb 268 2 |
|
/gems/activerecord-3.2.12/lib/active_record/scoping/default.rb 123 2 |
|
/gems/arel-3.0.2/lib/arel.rb 39 2 |
|
/gems/arel-3.0.2/lib/arel/visitors/to_sql.rb 134 2 |
|
/gems/arel-3.0.2/lib/arel/visitors/to_sql.rb 136 2 |
|
/gems/arel-3.0.2/lib/arel/visitors/to_sql.rb 187 2 |
|
/gems/arel-3.0.2/lib/arel/visitors/to_sql.rb 282 2 |
|
/gems/arel-3.0.2/lib/arel/visitors/to_sql.rb 366 2 |
|
test.rb 6 2 |
|
/gems/activerecord-3.2.12/lib/active_record/connection_adapters/abstract/connection_specification.rb 149 3 |
|
/gems/activesupport-3.2.12/lib/active_support/log_subscriber.rb 91 3 |
|
/gems/activerecord-3.2.12/lib/active_record/scoping.rb 130 4 |
|
/gems/activerecord-3.2.12/lib/active_record/scoping.rb 126 5 |
|
/gems/activerecord-3.2.12/lib/active_record/relation/spawn_methods.rb 14 6 |
|
/gems/activerecord-3.2.12/lib/active_record/relation/spawn_methods.rb 26 8 |
|
/gems/activerecord-3.2.12/lib/active_record/relation/spawn_methods.rb 52 12 |
|
/gems/activerecord-3.2.12/lib/active_record/base.rb 514 30 |
|
/gems/activerecord-3.2.12/lib/active_record/model_schema.rb 162 30 |
|
/gems/activerecord-3.2.12/lib/active_record/relation.rb 26 32 |
|
/gems/activerecord-3.2.12/lib/active_record/connection_adapters/postgresql_adapter.rb 665 38 |
|
/gems/activerecord-3.2.12/lib/active_record/result.rb 33 38 |
|
/gems/activerecord-3.2.12/lib/active_record/relation.rb 27 40 |
|
/gems/activerecord-3.2.12/lib/active_record/inheritance.rb 68 60 |
|
/gems/activesupport-3.2.12/lib/active_support/callbacks.rb 81 60 |
|
/gems/activesupport-3.2.12/lib/active_support/callbacks.rb 414 180 |
|
/gems/activerecord-3.2.12/lib/active_record/connection_adapters/postgresql_adapter.rb 605 910 |
|
1 Reply |
|
|
|
samSam Saffronco-founderMar '13 1 tenderlove |
|
More profiling (both warmed up in prd) |
|
|
|
100.times do |
|
Topic.limit(30).to_a |
|
end |
|
vs. |
|
|
|
100.times do |
|
ActiveRecord::Base.connection.raw_connection.async_exec("select * from topics limit 30").values |
|
end |
|
sampler: |
|
|
|
ruby*:::cmethod-entry |
|
{ |
|
k = copyinstr(arg0); |
|
m = copyinstr(arg1); |
|
} |
|
|
|
tick-5000hz |
|
/k != 0/ |
|
{ |
|
@[k, m] = count(); |
|
} |
|
AR |
|
|
|
Hash each 72 |
|
String hash 82 |
|
Kernel freeze 87 |
|
PG::Result ftype 88 |
|
Thread [] 89 |
|
Module name 94 |
|
Array zip 107 |
|
Array each 120 |
|
Thread current 123 |
|
Class allocate 131 |
|
Fixnum abs 136 |
|
String intern 147 |
|
Hash delete 150 |
|
Kernel instance_variable_set 183 |
|
Hash []= 195 |
|
String to_s 195 |
|
String initialize 237 |
|
String to_sym 238 |
|
Kernel respond_to? 247 |
|
Fixnum to_s 286 |
|
Class superclass 349 |
|
PG::Connection async_exec 354 |
|
PG::Result values 383 |
|
#<Class:0x007ff6e8b9e510> relation 399 |
|
Module === 415 |
|
Kernel block_given? 450 |
|
Kernel hash 512 |
|
Kernel class 517 |
|
Hash [] 566 |
|
Symbol to_s 586 |
|
Hash key? 6810 |
|
Raw |
|
|
|
Mutexd current 1 |
|
Thread [] 1 |
|
Mutex unlock 3 |
|
Module name 8 |
|
Thread current 13 |
|
PG::Result values 78 |
|
PG::Connection async_exec 266 |
|
My particular concern here is all these extraneous calls to .key? , seems the sampler is really spending much time there. |
|
|
|
These key? calls are all coming form |
|
|
|
2 143160 vm_call_cfunc:cmethod-entry Hash key? /Users/sam/.rvm/gems/ruby-2.0.0-p0/gems/activerecord-3.2.12/lib/active_record/locking/optimistic.rb 174 |
|
2 143160 vm_call_cfunc:cmethod-entry Hash key? /Users/sam/.rvm/gems/ruby-2.0.0-p0/gems/activerecord-3.2.12/lib/active_record/attribute_methods/serialization.rb 66 |