sw/source/filter/xml/xmlimp.cxx  |    3 ++-
 sw/source/filter/xml/xmlimp.hxx  |    7 +++++++
 sw/source/filter/xml/xmltbli.cxx |   14 +++++++++++++-
 3 files changed, 22 insertions(+), 2 deletions(-)

New commits:
commit 1dd71d79e15bd8098e7c17c8fcea3748592a902f
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Fri Mar 31 10:51:32 2023 +0300
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Fri Mar 31 09:01:02 2023 +0000

    tdf#154486: use importer-local map to deduplicate table names
    
    ... instead of SwDoc::GetUniqueTableName. The latter is expensive with
    many tables, has O(n^2) complexity with rather large O, and in corner
    cases of thousands tables with no or duplicate names, is unacceptably
    slow.
    
    Changes the test case import time from 39 s to 23 s on my system.
    
    Change-Id: Ia461c860d56cbbfdcb25bacbb9cca4961ced885e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149817
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/sw/source/filter/xml/xmlimp.cxx b/sw/source/filter/xml/xmlimp.cxx
index a0dc24ed5162..6ea193f2bc3f 100644
--- a/sw/source/filter/xml/xmlimp.cxx
+++ b/sw/source/filter/xml/xmlimp.cxx
@@ -323,7 +323,8 @@ SwXMLImport::SwXMLImport(
     m_bBlock( false ),
     m_bOrganizerMode( false ),
     m_bInititedXForms( false ),
-    m_pDoc( nullptr )
+    m_pDoc( nullptr ),
+    m_sDefTableName(SwResId(STR_TABLE_DEFNAME))
 {
     InitItemImport();
 }
diff --git a/sw/source/filter/xml/xmlimp.hxx b/sw/source/filter/xml/xmlimp.hxx
index e23c7399d5ea..4c528155f24c 100644
--- a/sw/source/filter/xml/xmlimp.hxx
+++ b/sw/source/filter/xml/xmlimp.hxx
@@ -84,6 +84,10 @@ class SwXMLImport: public SvXMLImport
 
     SwDoc*      m_pDoc; // cached for getDoc()
 
+    // Optimization for new table name lookup
+    OUString m_sDefTableName; // See STR_TABLE_DEFNAME
+    std::map<OUString, sal_uInt32> m_aTableNameMap; // Last used indices for 
duplicating table names
+
     void                    InitItemImport();
     void                    FinitItemImport();
     void                    UpdateTextCollConditions( SwDoc *pDoc );
@@ -163,6 +167,9 @@ public:
 
     const SwDoc* getDoc() const;
     SwDoc* getDoc();
+
+    const OUString& GetDefTableName() { return m_sDefTableName; }
+    std::map<OUString, sal_uInt32>& GetTableNameMap() { return 
m_aTableNameMap; }
 };
 
 inline const SvXMLImportItemMapper& SwXMLImport::GetTableItemMapper() const
diff --git a/sw/source/filter/xml/xmltbli.cxx b/sw/source/filter/xml/xmltbli.cxx
index 1dadf0bcedda..08bcd27d11b8 100644
--- a/sw/source/filter/xml/xmltbli.cxx
+++ b/sw/source/filter/xml/xmltbli.cxx
@@ -1173,7 +1173,19 @@ SwXMLTableContext::SwXMLTableContext( SwXMLImport& 
rImport,
     }
     if( sTableName.isEmpty() )
     {
-        sTableName = pDoc->GetUniqueTableName();
+        // Optimization: use import's own map to create unique names, because
+        // SwDoc::GetUniqueTableName scans all the already present tables,
+        // builds a bitset using rather complex rules, and that has quadratic
+        // complexity. Try once, then fallback to SwDoc::GetUniqueTableName
+        auto& tableNameMap = rImport.GetTableNameMap();
+        sal_Int32 nextIx = ++tableNameMap[aName];
+        OUString test = aName.isEmpty()
+                                  ? OUString(rImport.GetDefTableName() + 
OUString::number(nextIx))
+                                  : OUString(aName + "_" + 
OUString::number(nextIx));
+        if (const SwTableFormat* pExisting = 
pDoc->FindTableFormatByName(test); !pExisting)
+            sTableName = test;
+        else
+            sTableName = pDoc->GetUniqueTableName();
         GetImport().GetTextImport()
             ->GetRenameMap().Add( XML_TEXT_RENAME_TYPE_TABLE, aName, 
sTableName );
     }

Reply via email to