diff --git a/mozilla/extensions/transformiix/docs/optimized-stylesheets.html b/mozilla/extensions/transformiix/docs/optimized-stylesheets.html new file mode 100644 index 00000000000..7fa07b8ce1c --- /dev/null +++ b/mozilla/extensions/transformiix/docs/optimized-stylesheets.html @@ -0,0 +1,199 @@ + +
++ This document outlines optimizations that we can perform on + stylesheets after a stylesheet is compiled, but before it is executed. +
+ + ++ People often write stylesheets like +
+<LRE> + <xsl:attribute name="foo"> + text here + <xsl:value-of select="@bar"/> + </xsl:attribute> ++ This could be optimized into an AVT like +
+<LRE foo="text here{@foo}">
+
+ This can be done both in templates and in attribute-sets
+
+
+
+ + When only the string-value or double-value of an RTF is being used it + is unneccesary to create an entire RTF. Instead we could set up a + string-handler and use the resulting string. +
+ ++ Once we have a node-set() function we could also have a special + handler that creates that resulting nodeset rather then + whatever-we-create-once-we-have-real-RTFs. That handler would be set + up when we can determain that a RTF is used only as argument to the + node-set() function. +
+ ++ In cases where an RTF is used as parameter in a call to another + template we could do further analysis to see how that parameter is + used in that template. Either by first analyzing how all template + parameters are used in all templates, or by recursivly searching + the called template when we find that a RTF is used as an argument. +
+ ++ We will still need a catch-all RTF implementation that is used when + we can't determin how a variable is used, or when it is used in + multiple different ways. +
+ + ++ Variables that does not have a value that depends on the source + document can be inlined into the stylesheet. The value of these + variables could also be calculated before the transformation is + started. +
+ ++ This can be combined with the previous optimization of RTFs so that + stylesheets like +
+<xsl:variable name="v">_</xsl:variable> +... +<xsl:value-of select="concat(@id, $v, foo)"/> ++ is executed like +
+<xsl:value-of select="concat(@id, '_', foo)"/> ++
+ +
+ This can be done for both global and local variables. +
+ + ++ Cross-references to named templates, attribute-sets and template-modes + can be resolved before the stylesheet is executed. That way we don't + have to search for the template/attribute-set with a certain name, or + the group of templates for a certain mode. +
+ ++ Note that for apply-imports we won't always know at compile-time which + mode to seach for templates in. +
+ + ++ Rather then seaching for variables with a certain name at runtime + we could remove names for variables/parameters entierly and put all + variables in an array (possibly a separate array for global variables) + and then let variable-references in expressions just point to an index + in that array. +
+ + ++ A lot of instruction-elements uses AVTs that often are constants in + stylesheets, such as the data-type parameter to xsl:sort. For xsl:sort + we could pre-create a finished nodesorter if all AVTs in all + xsl:sort-elements are constant. +
+ +
+ Another example is xsl:element and xsl:attribute where we could use
+ LRE-instructions if the AVTs are constant. For xsl:number we could
+ create prepare the list of txFormattedCounters.
+
+ If a template calls another template and uses the exact same + parameters we can reuse the same parameter-map. +
+<xsl:template name="hsbc_html_body"> + <xsl:param name="appName"/> + <xsl:param name="title"/> + <body> + <xsl:call-template name="hsbc_form"> + <xsl:with-param name="appName" select="$appName"/> + <xsl:with-param name="title" select="$title"/> + </xsl:call-template> + </body> +</xsl:template> ++ + +
+ We have to watch out for default parameter-values as well as + parameters being specified by the caller of this template but not used + by this template. I.e. if the parameter "hello" is specified when + calling the above template. +
+ ++ All this might make this optimization useless. +
+ +
+ When a template contains several consecutive "LRE instructions" such
+ as LRE-elements, LRE-attributes and textnodes we can replace their
+ instructions with a special instruction that contains a
+ txResultBuffer. This buffer would then be flushed when
+ the instruction is executed. This can of course not be done for
+ LRE-attributes that contains AVTs. Even PI and comment-instructions
+ can be included in this buffer if their contents is strictly literal.
+
+ The result is that a template like +
+<xsl:template match="/"> + <html> + <body bgcolor="green"> + Here goes pagecontent + <xsl:apply-templates /> + </body> + </html> +</xsl:template> ++ Would result in the first
txResultBuffer to contain the
+ following transactions: eStartElementTransaction,
+ eStartElementTransaction, eAttributeTransaction, eCharacterTransaction.
+
+
+ + There is probably a lower limit to when it's worth the effort to + replace the normal instructions with the buffer-instruction. A single + "LRE instruction" is probobably better kept as a normal instruction. +
+ + + diff --git a/mozilla/extensions/transformiix/docs/optimized-xpath.html b/mozilla/extensions/transformiix/docs/optimized-xpath.html new file mode 100644 index 00000000000..c5bbc96156c --- /dev/null +++ b/mozilla/extensions/transformiix/docs/optimized-xpath.html @@ -0,0 +1,490 @@ + + ++ This document outlines optimizations that we can perform to execute + xpath-expressions faster. +
+ ++ Speed up retrieval of orderInfo objects by storing them in resp. + node instead of in a hash. +
+ +
+ We currently spend a GREAT deal of time looking through a
+ DOMHelper::orders hash looking for the orderInfo object for a
+ specific node. If we moved the ownership and retrieval of these
+ orderInfo objects to the Node class instead we will probably save
+ a lot of time. I.E. instead of calling
+ myDOMHelper->getDocumentOrder(node) you call
+ node->getDocumentOrder() which then returns the
+ orderInfo object.
+
+ It would also be nice if we at the same time fixed some bugs wrt the + orderInfo objects and the function that sorts nodes using them. +
+ ++ Bugs filed at this are 88964 and 94471 +
+ + + ++ Speed up document-order sorting by having the XPath engine always + return document-ordered nodesets. +
+ ++ Currently the nodesets returned from the XPath engine are totally + unordered (or rather, have undefined order) which forces the XSLT + code to sort the nodesets. This is quite expensive since it requires + us to generate orderInfo objects for every node. Considering that + many XPath classes actually returns nodesets that are already + ordered in document order (or reversed document order) this seems a + bit unnecessary. +
+ ++ However we still need to handle the classes that don't by default + return document-ordered nodesets. A good example of this is the id() + function. For example "id('foo bar')" produces two nodes which the + id-function has no idea how they relate in terms of document order. + Another example is "foo | bar", where the UnionExpr object gets two + nodesets (ordered in document order since all XPath classes should + now return ordered nodesets) and need to merge them into a single + ordered nodeset. +
+ ++ Speed up evaluation of XPath expressions by using specialized + classes for common optimizable expressions. +
+ ++ Some common expressions are possible to execute faster if we have + classes that are specialized for them. For example the expression + "@foo" can be evaluated by simply calling |context->getAttributeNode + ("foo")|, instead we now walk all attributes of the context node and + filter each node using a AttributeExpr. Below is a list of + expressions that I can think of that are optimizable, but there are + probably more. +
+ ++ One thing that we IMHO should keep in mind is to only put effort on + optimising expressions that are actually used in realworld + stylesheets. For example "foo | foo", "foo | bar[0]" and + "foo[position()]" can all be optimised to "foo", but since noone + should be so stupid as to write such an expression we shouldn't + spend time or codesize on that. Of course we should return the + correct result according to spec for those expressions, we just + shouldn't bother with evaluating them fast. +
+ + ++ Apart from finding expression that we can evaluate more cleverly + there is also the problem of how and where do we create these + optimised objects instead of the unoptimised, general ones we create + now. And what are these optimised classes, should they be normal + Expr classes or should they be something else? We could also add + "optional" methods to Expr which have default implementations in + Expr, for example a ::isContextSensitive() which returns MB_TRUE + unless overridden. However we probably can't answer all this until + we know which expressions we want to optimised and how we want to + optimise them. +
+ ++ These expressions can be optimised: +
+ ++
+
+
+
+
+
+
+
+
+
+
+ Refcount ExprResults to reduce the number of objects
+ created during evaluation.
+
+ Right now every subexpression creates a new object during evaluation. + If we refcounted objects we would be often be able to reuse the same + objects across multiple evaluations. We should also keep global + result-objects for true and false, that way expressions that return + bool-values would never have to create any objects. +
+ ++ This does however require that the returned objects arn't modified + since they might be used elsewhere. This is not a big problem in the + current code where we pretty much only modify nodesets in a couple + of places. +
+ +
+ To be able to reuse objects across subexpressions we chould have an
+ ExprResult::ensureModifyable-function. This would
+ return the same object if the refcount is 1, and create a new object
+ to return otherwise. This is especially usefull for nodesets which
+ would be mostly used by a single object at a time. But it could be
+ just as usefull for other types, though then we might need a
+ ExprResult::ensureModifyableOfType(ExprResult::ResultType)-function
+ that only returned itself if it has a refcount of 1 and is of the
+ requsted type.
+
+ Detect when we can concatenate nodesets instead of merge them in + PathExpr. +
+ ++ Why can we for expressions like "foo/bar/baz" concatenate the resulting + nodesets without having to check nodeorder? Because at every step two + statements are true: +
+ For example; While evaluating the second step in "foo/bar/baz" we + iterate a nodelist containing all "foo" children of the original + contextnode, i.e. none can be an ancestor of another. And the + LocationStep "bar" only returns children of the contextnode. +
+ ++ So, it would be nice if we can detect when this occurs as often as + possible. For example the expression "id(foo)/bar/baz" fulfils those + requirements if the nodeset returned from contains doesn't contain any + ancestors of other nodes in the nodeset, which probably often is the + case in real-world stylesheets. +
+ ++ We should perform this check on every step to be able to take advantage + of it as often as possible. For example the in expression + "id(@boss)/ancestor::team/members" we can't use this optimisation at the + second step since the ancestor axis returns nodes that are not members + of the contextnodes subtree. However we will probably be able to use the + optimisation at the third step since if iterated nodeset contains only + one node (and thus can't contain ancestors of it's members). +
+ +