dbertoni    01/01/15 18:52:36

  Modified:    c/src/XalanSourceTree XalanSourceTreeContentHandler.cpp
                        XalanSourceTreeContentHandler.hpp
                        XalanSourceTreeHelper.cpp XalanSourceTreeHelper.hpp
  Log:
  Cache last node appended to fix major performance degradation with broad 
documents.
  
  Revision  Changes    Path
  1.4       +111 -32   
xml-xalan/c/src/XalanSourceTree/XalanSourceTreeContentHandler.cpp
  
  Index: XalanSourceTreeContentHandler.cpp
  ===================================================================
  RCS file: 
/home/cvs/xml-xalan/c/src/XalanSourceTree/XalanSourceTreeContentHandler.cpp,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- XalanSourceTreeContentHandler.cpp 2000/12/29 03:23:26     1.3
  +++ XalanSourceTreeContentHandler.cpp 2001/01/16 02:52:35     1.4
  @@ -68,6 +68,7 @@
   
   #include "XalanSourceTreeDocument.hpp"
   #include "XalanSourceTreeElement.hpp"
  +#include "XalanSourceTreeHelper.hpp"
   
   
   
  @@ -80,6 +81,8 @@
        m_document(theDocument),
        m_currentElement(0),
        m_elementStack(),
  +     m_lastChild(0),
  +     m_lastChildStack(),
        m_ownsDocument(false),
        m_accumulateText(fAccumulateText),
        m_textBuffer()
  @@ -125,7 +128,12 @@
   void
   XalanSourceTreeContentHandler::endDocument()
   {
  +     // Pop off the dummy value that we pushed in 
  +     // startDocument()...
  +     m_elementStack.pop_back();
  +
        assert(m_elementStack.empty() == true);
  +     assert(m_lastChildStack.empty() == true);
   
        assert(isEmpty(m_textBuffer) == true);
   }
  @@ -138,6 +146,7 @@
                        const XMLCh* const      /* localname */, 
                        const XMLCh* const      /* qname */)
   {
  +     // Process any text that we may have accumulated...
        processAccumulatedText();
   
        assert(m_elementStack.empty() == false);
  @@ -145,20 +154,71 @@
        // Pop the element of the stack...
        m_elementStack.pop_back();
   
  +     assert(m_elementStack.empty() == false);
  +
        // Get the element from the back of the
  -     // stack, if any...
  -     if (m_elementStack.empty() == false)
  +     // stack.
  +     m_currentElement = m_elementStack.back();
  +
  +     assert(m_lastChildStack.empty() == false);
  +
  +     m_lastChild = m_lastChildStack.back();
  +
  +     // Pop the last child stack
  +     m_lastChildStack.pop_back();
  +}
  +
  +
  +
  +// A helper function to manage appending the new child.
  +template <class ParentNodeType, class ChildNodeType>
  +inline void
  +doAppendChildNode(
  +                     ParentNodeType*         theParent,
  +                     XalanNode*&                     theLastChild,
  +                     ChildNodeType           theNewChild)
  +{
  +     assert(theParent != 0);
  +     assert(theNewChild != 0);
  +
  +     if (theLastChild == 0)
        {
  -             m_currentElement = m_elementStack.back();
  +             theParent->appendChildNode(theNewChild);
        }
        else
        {
  -             m_currentElement = 0;
  +             XalanSourceTreeHelper::appendSibling(theLastChild, theNewChild);
        }
  +
  +     theLastChild = theNewChild;
   }
   
   
   
  +// A helper function to manage appending the new child.
  +template <class ChildNodeType>
  +inline void
  +doAppendChildNode(
  +                     XalanSourceTreeDocument*        theDocument,
  +                     XalanSourceTreeElement*         theCurrentElement,
  +                     XalanNode*&                                     
theLastChild,
  +                     ChildNodeType                           theNewChild)
  +{
  +     assert(theDocument != 0);
  +     assert(theNewChild != 0);
  +
  +     if (theCurrentElement == 0)
  +     {
  +             doAppendChildNode(theDocument, theLastChild, theNewChild);
  +     }
  +     else
  +     {
  +             doAppendChildNode(theCurrentElement, theLastChild, theNewChild);
  +     }
  +}
  +
  +
  +
   void
   XalanSourceTreeContentHandler::ignorableWhitespace(
                        const XMLCh* const      chars,
  @@ -167,9 +227,14 @@
        // Ignore any whitespace reported before the document element has been 
parsed.
        if (m_elementStack.empty() == false)
        {
  +             assert(m_currentElement != 0);
  +
                processAccumulatedText();
  +
  +             XalanSourceTreeText*    theNewTextNode =
  +                     m_document->createTextIWSNode(chars, length, 
m_currentElement);
   
  -             
m_currentElement->appendChildNode(m_document->createTextIWSNode(chars, length, 
m_currentElement));
  +             doAppendChildNode(m_currentElement, m_lastChild, 
theNewTextNode);
        }
   }
   
  @@ -180,18 +245,16 @@
                const XMLCh* const      target,
                const XMLCh* const      data)
   {
  -     if (m_currentElement == 0)
  -     {
  -             assert(m_document != 0);
  +     processAccumulatedText();
   
  -             
m_document->appendChildNode(m_document->createProcessingInstructionNode(target, 
data));
  -     }
  -     else
  -     {
  -             processAccumulatedText();
  +     XalanSourceTreeProcessingInstruction* const             theNewPI =
  +             m_document->createProcessingInstructionNode(target, data, 
m_currentElement);
   
  -             
m_currentElement->appendChildNode(m_document->createProcessingInstructionNode(target,
 data, m_currentElement));
  -     }
  +     doAppendChildNode(
  +                     m_document,
  +                     m_currentElement,
  +                     m_lastChild,
  +                     theNewPI);
   }
   
   
  @@ -206,6 +269,7 @@
   void
   XalanSourceTreeContentHandler::startDocument()
   {
  +     // Clean up and reset everything...
        if (m_document == 0)
        {
                m_document = new XalanSourceTreeDocument;
  @@ -217,16 +281,28 @@
                m_document = new XalanSourceTreeDocument;
        }
   
  +     m_currentElement = 0;
  +
        m_elementStack.clear();
   
        m_elementStack.reserve(eDefaultStackSize);
   
  +     m_lastChild = 0;
  +
  +     m_lastChildStack.clear();
  +
  +     m_lastChildStack.reserve(eDefaultStackSize);
  +
        if (m_accumulateText == true)
        {
                clear(m_textBuffer);
   
                reserve(m_textBuffer, eDefaultTextBufferSize);
        }
  +
  +     // Push a dummy value for the current element, so we
  +     // don't have to check for an empty stack in endElement().
  +     m_elementStack.push_back(0);
   }
   
   
  @@ -243,18 +319,19 @@
        XalanSourceTreeElement* const   theNewElement =
                createElement(uri, localname, qname, attrs, m_currentElement);
   
  -     if (m_currentElement == 0)
  -     {
  -             m_document->appendChildNode(theNewElement);
  -     }
  -     else
  -     {
  -             m_currentElement->appendChildNode(theNewElement);
  -     }
  +     doAppendChildNode(
  +                     m_document,
  +                     m_currentElement,
  +                     m_lastChild,
  +                     theNewElement);
   
        m_elementStack.push_back(theNewElement);
   
  +     m_lastChildStack.push_back(m_lastChild);
  +
        m_currentElement = theNewElement;
  +
  +     m_lastChild = 0;
   }
   
   
  @@ -325,14 +402,11 @@
        XalanSourceTreeComment* const   theNewComment =
                m_document->createCommentNode(chars, length, m_currentElement);
   
  -     if (m_currentElement != 0)
  -     {
  -             m_currentElement->appendChildNode(theNewComment);
  -     }
  -     else
  -     {
  -             m_document->appendChildNode(theNewComment);
  -     }
  +     doAppendChildNode(
  +                     m_document,
  +                     m_currentElement,
  +                     m_lastChild,
  +                     theNewComment);
   }
   
   
  @@ -451,5 +525,10 @@
                        const XMLCh*    chars,
                        unsigned int    length)
   {
  -     m_currentElement->appendChildNode(m_document->createTextNode(chars, 
length, m_currentElement));
  +     assert(m_currentElement != 0);
  +
  +     XalanSourceTreeText*    theNewTextNode = 
  +                             m_document->createTextNode(chars, length, 
m_currentElement);
  +
  +     doAppendChildNode(m_currentElement, m_lastChild, theNewTextNode);
   }
  
  
  
  1.4       +23 -0     
xml-xalan/c/src/XalanSourceTree/XalanSourceTreeContentHandler.hpp
  
  Index: XalanSourceTreeContentHandler.hpp
  ===================================================================
  RCS file: 
/home/cvs/xml-xalan/c/src/XalanSourceTree/XalanSourceTreeContentHandler.hpp,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- XalanSourceTreeContentHandler.hpp 2000/12/29 03:23:26     1.3
  +++ XalanSourceTreeContentHandler.hpp 2001/01/16 02:52:35     1.4
  @@ -78,6 +78,7 @@
   
   
   
  +class XalanNode;
   class XalanSourceTreeDocument;
   class XalanSourceTreeElement;
   
  @@ -90,8 +91,10 @@
   
   #if defined(XALAN_NO_NAMESPACES)
        typedef vector<XalanSourceTreeElement*>                 
ElementStackType;
  +     typedef vector<XalanNode*>                                              
LastChildStackType;
   #else
        typedef std::vector<XalanSourceTreeElement*>    ElementStackType;
  +     typedef std::vector<XalanNode*>                                 
LastChildStackType;
   #endif
   
        enum { eDefaultStackSize = 50, eDefaultTextBufferSize = 100 };
  @@ -250,16 +253,36 @@
   
   
        // Data members...
  +
  +     // The current document we're building...
        XalanSourceTreeDocument*        m_document;
   
  +     // The current element...
        XalanSourceTreeElement*         m_currentElement;
   
  +     // Stack of elements...
        ElementStackType                        m_elementStack;
   
  +     // The last child appended to the current element.  This is
  +     // an important optimization, because XalanSourceTreeElement
  +     // does not have a pointer to it's last child.  Without this,
  +     // appending a child becomes a linear search.
  +     XalanNode*                                      m_lastChild;
  +
  +     // Stack of last children appended.  There is a ono-to-one
  +     // correspondance to the entries in m_elementStack.
  +     LastChildStackType                      m_lastChildStack;
  +
  +     // If true, the instance owns the document and will delete
  +     // it when necessary.
        bool                                            m_ownsDocument;
   
  +     // If true, the handler will accumulate text from calls to
  +     // characters() until another event triggers the creation
  +     // of the node.
        const bool                                      m_accumulateText;
   
  +     // A buffer to hold accumulated text.
        XalanDOMString                          m_textBuffer;
   };
   
  
  
  
  1.4       +114 -21   xml-xalan/c/src/XalanSourceTree/XalanSourceTreeHelper.cpp
  
  Index: XalanSourceTreeHelper.cpp
  ===================================================================
  RCS file: 
/home/cvs/xml-xalan/c/src/XalanSourceTree/XalanSourceTreeHelper.cpp,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- XalanSourceTreeHelper.cpp 2000/12/19 02:34:28     1.3
  +++ XalanSourceTreeHelper.cpp 2001/01/16 02:52:35     1.4
  @@ -126,13 +126,13 @@
   template<class NodeType>
   inline void
   doAppendSibling(
  -                     XalanNode*      theNode,
  +                     XalanNode*      theSibling,
                        NodeType*       theNewSibling)
   {
  -     assert(theNode != 0);
  +     assert(theSibling != 0);
        assert(theNewSibling != 0);
   
  -     XalanNode* const        theLastSibling = 
XalanSourceTreeHelper::getLastSibling(theNode);
  +     XalanNode* const        theLastSibling = 
XalanSourceTreeHelper::getLastSibling(theSibling);
   
        switch(theLastSibling->getNodeType())
        {
  @@ -160,6 +160,42 @@
   
   
   
  +template<class NodeType>
  +inline void
  +doAppendToLastSibling(
  +                     XalanNode*      theLastSibling,
  +                     NodeType*       theNewSibling)
  +{
  +     assert(theLastSibling != 0);
  +     assert(theNewSibling != 0);
  +     assert(theLastSibling->getNextSibling() == 0);
  +
  +     switch(theLastSibling->getNodeType())
  +     {
  +     case XalanNode::COMMENT_NODE:
  +             castToComment(theLastSibling)->appendSiblingNode(theNewSibling);
  +             break;
  +
  +     case XalanNode::ELEMENT_NODE:
  +             castToElement(theLastSibling)->appendSiblingNode(theNewSibling);
  +             break;
  +
  +     case XalanNode::PROCESSING_INSTRUCTION_NODE:
  +             
castToProcessingInstruction(theLastSibling)->appendSiblingNode(theNewSibling);
  +             break;
  +
  +     case XalanNode::TEXT_NODE:
  +             castToText(theLastSibling)->appendSiblingNode(theNewSibling);
  +             break;
  +
  +     default:
  +             throw 
XalanDOMException(XalanDOMException::HIERARCHY_REQUEST_ERR);
  +             break;
  +     }
  +}
  +
  +
  +
   template <class NodeType1, class NodeType2>
   inline void
   append(
  @@ -317,6 +353,70 @@
   
   
   
  +void
  +XalanSourceTreeHelper::appendSibling(
  +                     XalanNode*                                      
theLastSibling,
  +                     XalanSourceTreeComment*         theNewLastSibling)
  +{
  +     doAppendToLastSibling(theLastSibling, theNewLastSibling);
  +}
  +
  +
  +
  +void
  +XalanSourceTreeHelper::appendSibling(
  +                     XalanNode*                                      
theLastSibling,
  +                     XalanSourceTreeElement*         theNewLastSibling)
  +{
  +     doAppendToLastSibling(theLastSibling, theNewLastSibling);
  +}
  +
  +
  +
  +void
  +XalanSourceTreeHelper::appendSibling(
  +                     XalanNode*                                              
                theLastSibling,
  +                     XalanSourceTreeProcessingInstruction*   
theNewLastSibling)
  +{
  +     doAppendToLastSibling(theLastSibling, theNewLastSibling);
  +}
  +
  +
  +
  +void
  +XalanSourceTreeHelper::appendSibling(
  +                     XalanNode*                              theLastSibling,
  +                     XalanSourceTreeText*    theNewLastSibling)
  +{
  +     doAppendToLastSibling(theLastSibling, theNewLastSibling);
  +}
  +
  +
  +
  +XalanNode*
  +doGetLastSibling(XalanNode*          theNode)
  +{
  +     if (theNode == 0)
  +     {
  +             return 0;
  +     }
  +     else
  +     {
  +             XalanNode*      theNextSibling = theNode->getNextSibling();
  +
  +             while(theNextSibling != 0)
  +             {
  +                     theNode = theNextSibling;
  +
  +                     theNextSibling = theNode->getNextSibling();
  +             }
  +
  +             return theNode;
  +     }
  +}
  +
  +
  +
   template <class NodeType>
   void
   doAppendSiblingToChild(
  @@ -332,7 +432,16 @@
                theNewSibling->setParentElement(theOwnerElement);
        }
   
  -     append(theFirstChildSlot, theNewSibling);
  +     if (theFirstChildSlot == 0)
  +     {
  +             append(theFirstChildSlot, theNewSibling);
  +     }
  +     else
  +     {
  +             XalanNode* const        theLastSibling = 
doGetLastSibling(theFirstChildSlot);
  +
  +             doAppendSibling(theLastSibling, theNewSibling); 
  +     }
   }
   
   
  @@ -385,21 +494,5 @@
   XalanNode*
   XalanSourceTreeHelper::getLastSibling(XalanNode*     theNode)
   {
  -     if (theNode == 0)
  -     {
  -             return 0;
  -     }
  -     else
  -     {
  -             XalanNode*      theNextSibling = theNode->getNextSibling();
  -
  -             while(theNextSibling != 0)
  -             {
  -                     theNode = theNextSibling;
  -
  -                     theNextSibling = theNode->getNextSibling();
  -             }
  -
  -             return theNode;
  -     }
  +     return doGetLastSibling(theNode);
   }
  
  
  
  1.3       +23 -8     xml-xalan/c/src/XalanSourceTree/XalanSourceTreeHelper.hpp
  
  Index: XalanSourceTreeHelper.hpp
  ===================================================================
  RCS file: 
/home/cvs/xml-xalan/c/src/XalanSourceTree/XalanSourceTreeHelper.hpp,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- XalanSourceTreeHelper.hpp 2000/12/17 22:26:59     1.2
  +++ XalanSourceTreeHelper.hpp 2001/01/16 02:52:35     1.3
  @@ -80,17 +80,9 @@
   {
   public:
   
  -     friend class XalanSourceTreeComment;
  -     friend class XalanSourceTreeDocument;
  -     friend class XalanSourceTreeElement;
  -     friend class XalanSourceTreeProcessingInstruction;
  -     friend class XalanSourceTreeText;
  -
        static XalanNode*
        getLastSibling(XalanNode*       theNode);
   
  -private:
  -
        static void
        appendSibling(
                        XalanSourceTreeDocument*        theDocument,
  @@ -121,11 +113,34 @@
                        XalanNode*&                             
theNextSiblingSlot,
                        XalanNode*                              theNewSibling);
   
  +     // New appendSibling interfaces...
  +     static void
  +     appendSibling(
  +                     XalanNode*                                      
theLastSibling,
  +                     XalanSourceTreeComment*         theNewLastSibling);
  +
  +     static void
  +     appendSibling(
  +                     XalanNode*                                      
theLastSibling,
  +                     XalanSourceTreeElement*         theNewLastSibling);
  +
        static void
  +     appendSibling(
  +                     XalanNode*                                              
                theLastSibling,
  +                     XalanSourceTreeProcessingInstruction*   
theNewLastSibling);
  +
  +     static void
  +     appendSibling(
  +                     XalanNode*                              theLastSibling,
  +                     XalanSourceTreeText*    theNewLastSibling);
  +
  +
  +     static void
        appendSiblingToChild(
                        XalanSourceTreeElement*         theOwnerElement,
                        XalanNode*&                                     
theChildSlot,
                        XalanSourceTreeComment*         theNewSibling);
  +
   
        static void
        appendSiblingToChild(
  
  
  

Reply via email to