Subject | Re: [Firebird-Architect] Re: embedding Lua as procedural language |
---|---|
Author | Dmitry Yemanov |
Post date | 2008-12-24T14:05:17Z |
paulruizendaal wrote:
costs do they eliminate:
"First, a syntax tree describes a program’s grammatical structure, not
the operations needed to execute it. Therefore, during execution, the
interpreter would repeatedly visit nodes that did no useful work. For
example, for the block “{ x++; }”, the interpreter would first visit the
block node “{…}”, which did nothing, and then visit its first child, the
increment node “x++”, which incremented x."
Our execution tree doesn't have any useless grammatical nodes, they're
eliminated during the SQL->BLR compilation. The only node that doesn't
perform any useful work itself is nod_list which acts as a container for
other nodes.
"Second, even nodes that did useful work were expensive to visit. Each
visit required a virtual function call and return, which meant a couple
of indirect memory reads to retrieve the function being called, and two
indirect branches—one for the call, and one for the return. On modern
hardware, “indirect” is a synonym for “slow”, since indirection tends to
defeat caching and branch prediction."
Our looper doesn't call any virtual methods, the entire node handling is
embedded. Hard to maintain but fast to execute.
"Third, to propagate execution state between nodes, the interpreter had
to pass around a bunch of data. For example, when processing a subtree
involving a local variable, the interpreter would copy the variable’s
value between all the nodes in the subtree. So, starting at the “x” part
of the expression “f((x) + 1)”, a variable node “x” would return x to a
parentheses node “(x)”, which would return x to a plus node “(x) + 1”.
Then, the plus node would return (x) + 1 to an argument list node “((x)
+ 1)”, which would copy that value into an argument list object, which,
in turn, it would pass to the function node for f."
Our state (aka impure area) is pre-allocated during the BLR compilation
phase and it's not transported between nodes during execution.
The funny thing is that some our ideas (replace the looper switch with
virtual functions, get rid of BLR and execute the SQL grammar tree
directly, etc) are going exactly wrong direction from the SquirrelFish
point of view. Maybe we'll have to utilize their experience when such
changes will be about to happen :-)
Dmitry
>I wouldn't be so optimistic. Let's analyze what runtime performance
> If the observations on that page are correct, than FB would benefit
> from refactoring 'looper' (essentially a parse tree walker coroutine)
> into a byte-code engine.
costs do they eliminate:
"First, a syntax tree describes a program’s grammatical structure, not
the operations needed to execute it. Therefore, during execution, the
interpreter would repeatedly visit nodes that did no useful work. For
example, for the block “{ x++; }”, the interpreter would first visit the
block node “{…}”, which did nothing, and then visit its first child, the
increment node “x++”, which incremented x."
Our execution tree doesn't have any useless grammatical nodes, they're
eliminated during the SQL->BLR compilation. The only node that doesn't
perform any useful work itself is nod_list which acts as a container for
other nodes.
"Second, even nodes that did useful work were expensive to visit. Each
visit required a virtual function call and return, which meant a couple
of indirect memory reads to retrieve the function being called, and two
indirect branches—one for the call, and one for the return. On modern
hardware, “indirect” is a synonym for “slow”, since indirection tends to
defeat caching and branch prediction."
Our looper doesn't call any virtual methods, the entire node handling is
embedded. Hard to maintain but fast to execute.
"Third, to propagate execution state between nodes, the interpreter had
to pass around a bunch of data. For example, when processing a subtree
involving a local variable, the interpreter would copy the variable’s
value between all the nodes in the subtree. So, starting at the “x” part
of the expression “f((x) + 1)”, a variable node “x” would return x to a
parentheses node “(x)”, which would return x to a plus node “(x) + 1”.
Then, the plus node would return (x) + 1 to an argument list node “((x)
+ 1)”, which would copy that value into an argument list object, which,
in turn, it would pass to the function node for f."
Our state (aka impure area) is pre-allocated during the BLR compilation
phase and it's not transported between nodes during execution.
The funny thing is that some our ideas (replace the looper switch with
virtual functions, get rid of BLR and execute the SQL grammar tree
directly, etc) are going exactly wrong direction from the SquirrelFish
point of view. Maybe we'll have to utilize their experience when such
changes will be about to happen :-)
Dmitry