Eliminating superclass lookup in the VM (and dynamic composition
of behavior)
Travis Griggs
tgriggs at keyww.com
Wed Dec 11 19:51:17 UTC 2002
tblanchard at mac.com wrote:
> I found myself sitting next to Ira Forman at an OOPSLA workshop in
> 1995. At the time he was one of the main designers of IBM's SOM
> library. It was something like his 3rd year presenting SOM. We were
> talking about how he handles multiple inheritance and he said his
> solution was to basically copy the dispatch table (method dict if you
> like) into each class.
>
> Partly because SOM allowed you to attach before, after, and around
> methods to arbitrary locations in the class hierarchy and the
> bookkeeping got too hairy if the point of dispatch was somewhere other
> than the attachment class.
>
> So I have heard of it being done. Sounds like the classic size v speed
> tradeoff. I'm a bit worried that the size of the image will explode.
All this conjecture and hypothesis about what will happen if you flatten
the method dictionaries... this is Smalltalk people. It's a 10 minute
excercise in a workspace to find out. I had VW handy, so I did it there
in a lightly loaded 7.1 image. But the technique is the same. It's not
100% accurate, but we don't care, we're just looking for a general feel.
Assuming that each method in a method dictionary takes up a 4 byte slot,
one can do something like:
inherited := Dictionary new.
SystemUtils allBehaviorsDo: [:class |
inherited at: class put: class getMethodDictionary size * 4].
flattened := Dictionary new.
SystemUtils allBehaviorsDo: [:class | | sum |
sum := 0.
class withAllSuperclasses do: [:each | sum := sum + (inherited at: each)].
"sum := sum - (inherited at: Object)." "uncomment to do without object"
flattened at: class put: sum].
totalInherited := inherited fold: [:a :b | a + b].
totalFlattened := flattened fold: [:a :b | a + b].
Transcript show: 'Inherited: '; print: totalInherited; show: '
Flattened: '; print: totalFlattened; show: ' Increase: '; print:
(totalFlattened - totalInherited / totalInherited) * 100.0; show: '%!
'
The results may surprise you. Here's the transcript output in my system:
Inherited: 203936 Flattened: 9749260 Increase: 4680.55%!
From 200K to nearly 10MB, that's cool. If you think about it, it
actually makes sense. Your taking objects with quite rich APIs (like
Object) and replicating that _everywhere_. Any large chunk of oft used
code (in Trait or Inherited form), in a flattened model will take
Subcribers * Behavior instead of (1 * Behavior) + (Subscribers * Chain
link size). So one, might think what if I do a hybrid. There's no sense
in traiting the very common Object API, so we leave out flattening
Object's method dictionary. For me, that produces:
Inherited: 203936 Flattened: 5026628 Increase: 2364.81%!
Someone run this for a well loaded Squeak image. I'm doing to see the
results! (Doesn't Morph have a gazillion methods and gazillion subclasses?)
--
Travis Griggs
Key Technology
One Man's Pink Plane is Another Man's Blue Plane
More information about the Squeak-dev
mailing list
|