sunspot/sunspot — pull request #215 by jeanmartin (2012-04-19 08:45:08+00:00)
Title: Cache instance adapters for performance

Environment: ruby 1.9.3p184, rails 3.2.3, sunspot(-rails) 2.0.0.pre.120417

Recently I noticed a serious performance issue with my search. While the Solr query returned within about 30ms displaying the results took in some cases more than 1-2 seconds. After some investigation I tracked the problem down:
As soon as I try to access the first result sunspot lazy loads all results. To do this it loops through the ancestors of each result class in order to find the correct instance adapter. Now here's the problem: Walking through all ancestor classes of my model takes around 30-50 ms! Since sunspot does not cache the instance adapter for a model class it repeats the loop for each result. With 25 search results this means a rediculous 750ms to 1,25sec of delay!

Since I use a lot of gems (like state_maching and acts_as_taggable_on) which add more ancestors to my models the huge amount of time may not occur for many others. This, however, are unacceptable results for me:

```
# puts User.ancestors => https://gist.github.com/2419527
a=Time.now; 25.times { puts User.ancestors }; puts Time.now-a
=> 1.146263

# Even ActiveRecord::Base.ancestors is sloooow:
a=Time.now; 25.times { puts ActiveRecord::Base.ancestors }; puts Time.now-a
=> 0.201385

# Using just an array of integers instead of an array of ancestors is fast:
a=Time.now; 25.times { puts (1..100).to_a }; puts Time.now-a
=> 0.020689
```

I patched sunspot/lib/sunspot/adapters.rb to cache the instance adapters of each class so for a list of Users the ancestors of the User class are only looped through once. I admit it's just a quick fix but I wanted to share, maybe someone want's to implement this in a cleaner way.