Registering an event of type DOMNodeInsertedIntoDocument and 
DOMNodeRemovedFromDocument significantly slows down insertion or removal upon 
any other DOM in the VM.
-------------------------------------------------------------------------------------------------------------------------------------------------------------------

                 Key: XERCESJ-1376
                 URL: https://issues.apache.org/jira/browse/XERCESJ-1376
             Project: Xerces2-J
          Issue Type: Improvement
          Components: DOM (Level 2 Events)
    Affects Versions: 2.9.1
            Reporter: Ludger Bünger


DOMNodeInsertedIntoDocument and DOMNodeRemovedFromDocument events do dom 
iterations over a whole subtree even if no event listeners are present in the 
event distribution path.

Dispatching DOMNodeInsertedIntoDocument and DOMNodeRemovedFromDocument events 
is quite time consuming since the respective events need to be thrown upon 
*every child* of the node removed or inserted.
This aproximies to a disturbing O(n log n) runtime with n being the number of 
nodes in the DOM *for each insertion or removal*.

Xerces2-J provides a very basic optimization for these events such that if 
there is no event listener of the event type to be dispatched registered in the 
global static event listener pool than we do not go into dispatching the event 
upon the whole subtree.

Thus, as soon as such an event listener is registered upon a document every 
insertion and removal significantly slows down.

What makes this thing really bad is issue 
https://issues.apache.org/jira/browse/XERCESJ-1345:
Currently the event listener tracking data structure is static and used 
globally by every document, thus this slowdown happens upon every document - 
not only those that have the respective event listener registered.

I have a significant improvement coded for these event types that I'd like to 
share which is already in productive use in our xerces2-j based application.
But this code is based upon my code i provided for issue #1345, thus the patch 
requires also the patch for issue #1345 to be applied to the xerces repository.

The basic idea is to check and inhibit dispatching of an event upon every node 
in the subtree if there is no event listener of the required type is registered 
in the event path.
The checks have to be sufficiently fast to not slow down the whole operation if 
no or only a few events need to be thrown.

These checks would be:
1) is there an event listener of the required type registered upon the document 
at all?

If not: do not dispatch at all - we definitely do not need to dispatch any of 
these "slow" events.

This check already exists already but only globally and is done in constant 
O(1) time.
Thus my solution requires issue #1345 (to which I already provided a patch) to 
be solved beforehand.

2) check whether there exists an event listener in the event path between the 
node removed/inserted and the document root.

If yes: no optimization possible, we definitely need to dispatch the event upon 
each node in the whole subtree of the node inserted/removed.

This check requires iterating from the node to its document root and thus takes 
O(log n) time in average.
Since node insertion/removal also requires dispatching 
DOMNodeInserted/DomNodeRemoved/DomSubtreeModified-events which themself require 
O(log n) time in average, we do not have a degration in runtime complexity by 
this check. However it has the potential to apply the optimization:

3) check whether any node in the subtree of the inserted/removed node has an 
event listener of type DOMNodeInsertedIntoDocument or 
DOMNodeRemovedFromDocument.

If not: do not dispatch at all - we definitely do not need to dispatch any of 
these "slow" events.

Checking this can be done in constant O(1) time if we track the number of these 
"slow event type" event listeners registered in the whole subtree represented 
by a node.
Thus this requires an additional field in NodeImpl.

Updating this field takes time itself:
a) constant time during insertion or removal of every child and
b) O(log n) time upon registering/unregistering of event listeners of the 
respective "slow event" types.

Having this additional field allows another significant optimization if 
condition 2 does not apply (which we already checked earlier):
4) We need to dispatch the respective event only upon those nodes inside the 
subtree of the inserted/removed node, that have such an event listener 
registered.
These nodes can be easily found by recursively iterating over every child node 
of the node inserted/removed while ommiting all those nodes that have no such 
event listeners registered determined by the additional field required to check 
condition 3) fast.


Ok, that's it.
I'd like to provide the code for solving this but my code depends upon issue 
#1345, thus, I would be glad to see my patch attached to issue #1345 be applied 
to the svn repository so I can provide my patch for this.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to