It shouldn't need to cache method caches for String at all. It is not extending String. It is extending a specific instance of String (or whichever other class that object happens to be - for the rest of this I'm assuming it's a String), and thus not even touching the String class, but the eigenclass of the object: >> module ContentTyped
>> attr_accessor :content_type
>> end
=> nil
>> foo = "bar"
=> "bar"
>> foo.extend(ContentTyped)
=> "bar"
>> foo.content_type
=> nil
>> "another string".content_type
NoMethodError: undefined method `content_type' for "another string":String
from (irb):31
Externally this eigenclass is not readily visible, but within MRI it is, and for the purposes of a method call, the immediate superclass of foo above is not String, but its own object-local class object.If you are right this might be one of those areas where there's room for quick-wins. It doesn't take a "clever JIT" to localise this damage by ensuring the method cache is only invalidated for whichever entity is extended (which in this case is no existing class, unless the object has been previously extended). As for your examples, I wonder if these people realize that their code is equivalent to instantiating a new class for every single object. To me ROAR for example just looks horribly conceptually broken. In effect they are creating a new class per object in order to add non-stateful behaviour, which just makes me want to rage (EDIT: and DCI makes me want to rage too, for different reasons - they could achieve most of the same by composition by wrapping the objects in static classes instead of dynamically extending the objects; to me these examples stands as prime examples of how the horrible performance of MRI leads to people making implementation choices they'd never make with a Ruby implementation where the things that can be made fast are fast). I don't care if that is never a fast case, as they have options that would be faster: include the representer modules in the resource class like Article, subclass and include, wrap it when needed. I want it to be easy to write fast Ruby code - I don't particularly care if pathologically crazy implementation choices remain slow... |
Whoops!