|
May 2007
[
bamboo
]
03:28, Tuesday, 22 May 2007
I've applied the same optimization technique to static method and binary operator dispatching and now we have: int*int: 1.1115984 list*int: 5.0773008 dynamicDispatch: 4.2661344 staticDispatch 1.4921456 Niiiice. Changes checked in by the way. [boo| technology]
10x improvement for dynamic dispatching OR how it took me 4 years to optimize duck typing
[
bamboo
]
07:58, Monday, 21 May 2007
Around 4 years ago (!) there was this discussion about how to support some dynamic language features on top of mono. One of the topics was optimizing dynamic dispatching and apparently my suggestion was redirected to nul. 4 years later here I am finally implementing the idea in order to take boo's dynamic dispatching performance to the next level. Before the optimization: $ build/booi performance/duckoperators.boo int*int: 1.101584 list*int: 29.0217312 dynamicDispatch: 51.9484224 staticDispatch 1.4921456 Each line reports how long it takes to execute the described operation with dynamic dispatching 5_000_000 times (except the last line which executes the same operation as the line before it but with static dispatching).
The first line tells us that it takes 1.10 seconds for boo to multiply two integer objects using dynamic dispatching.
We can see a huge overhead over static dispatching. After the optimization: $ build/booi performance/duckoperators.boo int*int: 1.101584 list*int: 27.755072 dynamicDispatch: 4.055832 staticDispatch 1.4821312 Niiiiiice. So this first stab got it from 52 seconds down to 4 seconds. Not bad at all. A few changes and we'll have the same benefits for dynamic dispatching over static methods. I hope this will have a huge impact on environments that rely heavily on dynamic dispatching such as Brail. Unfortunately though this optimization is only available when building for the .NET 2.0 profile. Soon in a source code repository near you.
[
bamboo
]
18:29, Saturday, 19 May 2007
I've just arrived in Seattle for the Microsoft DLR Compiler Lab. JB will be here soon and I heard Miguel is joining us as well. Fun! Looking forward to getting my first Boo Silverlight application running. One of the questions I'm here for is should we migrate Boo's duck typing support to be based on the DLR? On the pros side we get better integration with all the DLR languages and perhaps better performance when executing dynamic code. On the cons side it's an additional dependency (and not a very mature one for that matter). Thoughts?
[
bamboo
]
18:19, Saturday, 19 May 2007
I started reviewing the overload resolution code in the boo compiler this week. Very old and, let's say, very interesting code. It was based on a fuzzy scoring system I have no idea how I came up with. Well, these things happen. The new code is based on the concepts discussed here. Thanks Avish and Daniel for that! A few test cases (mostly varargs related) had to be reviewed to comply with the improved behavior so expect a few compilation errors when updating to the new code and please let us know of any strange behavior.
[
bamboo
]
21:58, Wednesday, 16 May 2007
Life looks good so let's consider a very simple data structure. A linked list: 1:import System.Collections
2:
3:class LinkedList(IEnumerable):
4:
5: _head as Node
6:
7: def constructor(*values):
8: for value in values:
9: Add(value)
10:
11: def Add(value):
12: _head = Node(value, _head)
13:
14: def GetEnumerator():
15: node = _head
16: while node is not null:
17: yield node.Value
18: node = node.Next
19:
20: class Node:
21:
22: _value as object
23: _next as Node
24:
25: def constructor(value, next as Node):
26: _value = value
27: _next = next
28:
29: Value:
30: get:
31: return _value
32:
33: Next:
34: get:
35: return _next
Our LinkedList class can be used like this: 1:list = LinkedList("Eric Idle",
2: "John Cleese",
3: "Graham Chapman",
4: "Terry Gilliam",
5: "Terry Jones",
6: "Michael Palim")
7:for item in list:
8: print item
Which unsurprisingly gives the following output: Michael Palim Terry Jones Terry Gilliam Graham Chapman John Cleese Eric Idle Now let's move on and store our beautifully crafted LinkedList instance with Db4o: 1:
2:using container = Db4oFactory.OpenFile(fname):
3: container.Set(list)
4:
Some time later: 1:
2:using container = Db4oFactory.OpenFile(fname):
3: list = container.Query(LinkedList).Next()
4: for item in list:
5: print item or "<null>"
6:
Which gives: Michael Palim Terry Jones Terry Gilliam Graham Chapman <null> Uh, oh... What's going on? Activation is going on, that's what it is. Activation is the process of populating the attributes of an object with previously stored data. Db4o activates an object the first time it is retrieved from the database and whenever instructed to do so by the application through IObjectContainer.Activate. During activation Db4o will also follow the references in the object graph activating any referenced objects until a configured activation depth is reached. We can make sense of the output if we consider that Db4o has its default activation depth set to 5. When activating the list Db4o will follow the LinkedList._head reference and activate the first node, then follow the Node._next reference and so on until it reaches the 5th node which it's not activated further and has its members set to null. Now that we can understand the output has life gotten any easier? Well, we can ask Db4o to activate the list to the depth of 7: 1:
2:using container = Db4oFactory.OpenFile(configuration, fname):
3: list = container.Query(LinkedList).Next()
4: container.Activate(list, 7)
5: for item in list:
6: print item or "<null>"
Which gives us the correct output but smells funny. Application logic shouldn't have to worry about activation depth and all that. And how are we supposed to track the required activation depth for these dynamic object graphs? Enter Transparent Activation. Transparent Activation works by giving the objects in the system the responsibility of activating themselves before accessing any attribute. The activation must happen through a provided activator object which keeps track of everything needed for activation to work. The activator object is made available to any object that implements the IActivatable interface: 1:
2:class LinkedList(IEnumerable , IActivatable):
3:
4: _head as Node
5:
6: transient _activator as IActivator
7:
8: def constructor(*values):
9: for value in values:
10: Add(value)
11:
12: def Add(value):
13: Activate()
14: _head = Node(value, _head)
15:
16: def GetEnumerator():
17: Activate()
18: node = _head
19: while node is not null:
20: yield node.Value
21: node = node.Next
22:
23: def IActivatable.Bind(activator as IActivator):
24: _activator = activator
25:
26: def Activate():
27: if _activator is null: return
28: _activator.Activate()
29:
30: class Node(IActivatable):
31:
32: _value as object
33:
34: _next as Node
35:
36: transient _activator as IActivator
37:
38: def constructor(value, next as Node):
39: _value = value
40: _next = next
41:
42: Value:
43: get:
44: Activate()
45: return _value
46:
47: Next:
48: get:
49: Activate()
50: return _next
51:
52: def IActivatable.Bind(activator as IActivator):
53: _activator = activator
54:
55: private def Activate():
56: if _activator is null: return
57: _activator.Activate()
58:
The application just needs to enable Transparent Activation once and then everything should work as expected (no more explicit Activate calls from the application): 1:
2:configuration = Db4oFactory.NewConfiguration()
3:configuration.Add(TransparentActivationSupport())
4:
5:using container = Db4oFactory.OpenFile(configuration, fname):
6: list = container.Query(LinkedList).Next()
7: for item in list:
8: print item or "<null>"
Life looks better but what about all that boilerplate code that must go into the object model? The next Db4o release will ship with an instrumentation tool capable of injecting the right IL instructions into an object model to make it Transparent Activation ready. If you are curious to see this code in action grab it here. In a next blog entry I'll go into how to encapsulate this logic behind a smart boo attribute.
[
bamboo
]
10:17, Monday, 7 May 2007
Boo 0.7.7 is finally here! With special thanks to Avishay Lavie, Cedric Vivier and all the nice people who contributed to this release: Andy Bulka, Arron Washington, Chris Peterson, Daniel Grunwald, Dominik Zablotny, Doug Holton, Hans-Christian Holm, J Bryan Kelly, Jaroslaw Kowalski, Joshua W. Biagio, Marcus Griep, mfowle, Miguel de Icaza, Posti Laatikko, Sergio Rubio, Snaury, Szymon Wrozynski. What? - http://boo.codehaus.org/ Highlights for this release include: Check the full change log here. Best wishes and stay beautiful! |