sw/inc/ndarr.hxx | 1 sw/inc/ndindex.hxx | 40 ++++++++++++++++++++------------------- sw/inc/node.hxx | 2 + sw/source/core/docnode/nodes.cxx | 11 +++++----- 4 files changed, 29 insertions(+), 25 deletions(-)
New commits: commit 16c9053fe54b7c751b5c8c41ec7609199ebd6610 Author: Noel Grandin <noel.gran...@collabora.co.uk> AuthorDate: Tue Aug 13 13:13:42 2024 +0200 Commit: Noel Grandin <noel.gran...@collabora.co.uk> CommitDate: Thu Aug 15 18:49:12 2024 +0200 tdf#158556 move m_vIndices to SwNode When we load complex documents we end up with very large amounts of SwNodeIndex objects, and we also need call RemoveNode often, which means we end up scanning tons of objects. So move the linked list from SwNodes to SwNode, so we can scan just the objects that we are interested in. Shaves 10% off the load time of a complex docx file. Change-Id: Id62388dbc7e41fae30acb7910a982710c80e563e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/171888 Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk> Tested-by: Jenkins diff --git a/sw/inc/ndarr.hxx b/sw/inc/ndarr.hxx index 886384aca288..7bcebeda22db 100644 --- a/sw/inc/ndarr.hxx +++ b/sw/inc/ndarr.hxx @@ -95,7 +95,6 @@ class SwNodes final friend class SwStartNode; friend class ::sw::DocumentContentOperationsManager; - SwNodeIndex* m_vIndices; ///< ring of all indices on nodes. void RemoveNode( SwNodeOffset nDelPos, SwNodeOffset nLen, bool bDel ); void InsertNode( SwNode* pNode, const SwNodeIndex& rPos ); diff --git a/sw/inc/ndindex.hxx b/sw/inc/ndindex.hxx index 5ebc32846739..0f0cdabccee9 100644 --- a/sw/inc/ndindex.hxx +++ b/sw/inc/ndindex.hxx @@ -33,28 +33,26 @@ class SAL_WARN_UNUSED SW_DLLPUBLIC SwNodeIndex final : public sw::Ring<SwNodeInd void RegisterIndex() { - SwNodes& rNodes = GetNodes(); - if(!rNodes.m_vIndices) + if(!m_pNode->m_vIndices) { #if defined(__GNUC__) && (__GNUC__ == 12 || __GNUC__ == 13) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdangling-pointer" #endif - rNodes.m_vIndices = this; + m_pNode->m_vIndices = this; #if defined(__GNUC__) && (__GNUC__ == 12 || __GNUC__ == 13) #pragma GCC diagnostic pop #endif } - MoveTo(rNodes.m_vIndices); + MoveTo(m_pNode->m_vIndices); } void DeRegisterIndex() { - SwNodes& rNodes = GetNodes(); - if(rNodes.m_vIndices == this) - rNodes.m_vIndices = GetNextInRing(); + if(m_pNode->m_vIndices == this) + m_pNode->m_vIndices = GetNextInRing(); MoveTo(nullptr); - if(rNodes.m_vIndices == this) - rNodes.m_vIndices = nullptr; + if(m_pNode->m_vIndices == this) + m_pNode->m_vIndices = nullptr; } SwNodeIndex(SwNode* pNode) : m_pNode(pNode) { RegisterIndex(); } @@ -155,31 +153,35 @@ public: inline SwNodeIndex& SwNodeIndex::operator=( SwNodeOffset const nNew ) { - m_pNode = GetNodes()[ nNew ]; + auto pNewNode = GetNodes()[ nNew ]; + if (pNewNode != m_pNode) + { + DeRegisterIndex(); + m_pNode = GetNodes()[ nNew ]; + RegisterIndex(); + } return *this; } SwNodeIndex& SwNodeIndex::operator=( const SwNode& rNd ) { - if (&GetNodes() != &rNd.GetNodes()) + if (&rNd != m_pNode) { DeRegisterIndex(); m_pNode = const_cast<SwNode*>(&rNd); RegisterIndex(); } - else - m_pNode = const_cast<SwNode*>(&rNd); return *this; } SwNodeIndex& SwNodeIndex::Assign( const SwNode& rNd, SwNodeOffset nOffset ) { - *this = rNd; - - if( nOffset ) - m_pNode = GetNodes()[ GetIndex() + nOffset ]; - - return *this; + const SwNode* pNewNode; + if (nOffset) + pNewNode = rNd.GetNodes()[ rNd.GetIndex() + nOffset ]; + else + pNewNode = &rNd; + return operator=(*pNewNode); } #endif diff --git a/sw/inc/node.hxx b/sw/inc/node.hxx index 5e968000cccf..d8eaeaa9058a 100644 --- a/sw/inc/node.hxx +++ b/sw/inc/node.hxx @@ -97,6 +97,7 @@ class SW_DLLPUBLIC SwNode : public sw::BorderCacheOwner, private BigPtrEntry { friend class SwNodes; + friend class SwNodeIndex; SwNodeType m_nNodeType; @@ -105,6 +106,7 @@ class SW_DLLPUBLIC SwNode bool m_bIgnoreDontExpand : 1; ///< for Text Attributes - ignore the flag mutable sw::AccessibilityCheckStatus m_aAccessibilityCheckStatus; + SwNodeIndex* m_vIndices { nullptr }; ///< ring of indices pointing to this node. public: /// sw_redlinehide: redline node merge state diff --git a/sw/source/core/docnode/nodes.cxx b/sw/source/core/docnode/nodes.cxx index 46f4a4aa8f46..e11ee0ce49d8 100644 --- a/sw/source/core/docnode/nodes.cxx +++ b/sw/source/core/docnode/nodes.cxx @@ -60,7 +60,7 @@ static sal_uInt16 HighestLevel( SwNodes & rNodes, const SwNodeRange & rRange ); * @param rDocument TODO: provide documentation */ SwNodes::SwNodes( SwDoc& rDocument ) - : m_vIndices(nullptr), m_rMyDoc( rDocument ) + : m_rMyDoc( rDocument ) { m_bInNodesDel = m_bInDelUpdOutline = false; @@ -2390,11 +2390,12 @@ void SwNodes::RemoveNode( SwNodeOffset nDelPos, SwNodeOffset nSz, bool bDel ) SwNodeOffset nEnd = nDelPos + nSz; SwNode* pNew = (*this)[ nEnd ]; - for (SwNodeIndex& rIndex : m_vIndices->GetRingContainer()) + for (SwNodeOffset nCnt(0); nCnt < nSz; nCnt++) { - SwNodeOffset const nIdx = rIndex.GetIndex(); - if (nDelPos <= nIdx && nIdx < nEnd) - rIndex = *pNew; + SwNode* pNode = (*this)[ nDelPos + nCnt ]; + // the assignment will de-link the entry from the ring + while (pNode->m_vIndices) + (*pNode->m_vIndices) = *pNew; } std::vector<BigPtrEntry> aTempEntries;