A Question
Lately, this has become something of a design pattern for me: A base class describes a type of behavior, and rather than subclasses inheriting the base class’s behavior (which tend to just raise NotImplementedErrors), the subclasses override the base class’s methods to do their own thing. The catch, of course, is that some of the base class’s methods are not, in fact, just stubs. Some of them actually dispatch the message just received to each of the subclasses. So if you send GentleCMS::Cache the :clear message, that message will actually get relayed to GentleCMS::ResponseCache, GentleCMS::ResourceCache, and GentleCMS::RouteCache, thus clearing out all caching systems within GentleCMS. This allows for either selective or indiscriminate clearing of the cache. Very useful.
The problem is that my method for finding subclasses is slow, and I was hoping that you, Dear Readers, might have some suggestions for how I might improve the performance of this method:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
class Module #:nodoc: # Returns a list of modules and classes that descend from this module. def descendants descendant_modules = [] ObjectSpace.each_object do |object| next if !object.kind_of? Module next if object == self descendant_modules << object if object.ancestors.include? self end return descendant_modules end end |
I tend to cache the results of calling this method, so it doesn’t have a huge performance hit during normal operation, but startup times have become rather surprisingly long.
Update: I discovered that ObjectSpace.each_object could take an optional type parameter. The code runs much faster now:
1 2 3 4 5 6 7 8 9 10 11 12 |
class Module #:nodoc: # Returns a list of modules and classes that descend from this module. def descendants descendant_modules = [] ObjectSpace.each_object(Module) do |object| next if object == self descendant_modules << object if object.ancestors.include? self end return descendant_modules end end |
Update: Cool, that took the worst-case startup times down from 12 seconds to a worst-case startup time of 3 seconds. Not bad, a 400% overall performance improvement from changing two lines of code. I can live with that.