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