sc/inc/cellform.hxx                    |    8 +++
 sc/inc/cellformtmpl.hxx                |   69 +++++++++++++++++++++++++++++++++
 sc/inc/queryevaluator.hxx              |    7 +++
 sc/source/core/data/queryevaluator.cxx |   58 +++++++++++++++++++--------
 sc/source/core/tool/cellform.cxx       |   33 ++-------------
 5 files changed, 130 insertions(+), 45 deletions(-)

New commits:
commit 0ba21e561705ef174c8c0f4e10985f2b24c76b3d
Author:     Caolán McNamara <caolan.mcnam...@collabora.com>
AuthorDate: Sat Oct 26 20:14:17 2024 +0100
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Sun Oct 27 15:17:39 2024 +0100

    add a visitor contraption to avoid Reference counting costs
    
    brings my save times from 8.7s to to 5.85s
    
    Change-Id: I7f3ebbed78ee4d59f4ed9d04f1e35d2ea69a0c01
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/175689
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    Tested-by: Jenkins

diff --git a/sc/inc/cellform.hxx b/sc/inc/cellform.hxx
index f1efb330746e..5227001a76e3 100644
--- a/sc/inc/cellform.hxx
+++ b/sc/inc/cellform.hxx
@@ -49,6 +49,14 @@ public:
         const ScDocument& rDoc, svl::SharedStringPool& rStrPool,
         bool bFiltering = false, bool bForceSystemLocale = false );
 
+    // Similar to GetInputSharedString, but can be used to visit the source of 
the
+    // svl::SharedString to avoid reference counting overhead
+    template <typename TFunctor>
+    static auto visitInputSharedString(
+        const ScRefCellValue& rCell, sal_uInt32 nFormat, ScInterpreterContext* 
pContext,
+        const ScDocument& rDoc, svl::SharedStringPool& rStrPool,
+        bool bFiltering, bool bForceSystemLocale, const TFunctor& rOper);
+
     static OUString GetInputString(
         const ScRefCellValue& rCell, sal_uInt32 nFormat, ScInterpreterContext* 
pContext,
         const ScDocument& rDoc, bool bFiltering = false, bool 
bForceSystemLocale = false );
diff --git a/sc/inc/cellformtmpl.hxx b/sc/inc/cellformtmpl.hxx
new file mode 100644
index 000000000000..a36ba17a8bbb
--- /dev/null
+++ b/sc/inc/cellformtmpl.hxx
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "cellform.hxx"
+
+#include <svl/numformat.hxx>
+#include <svl/sharedstring.hxx>
+#include <svl/sharedstringpool.hxx>
+
+#include "formulacell.hxx"
+#include "document.hxx"
+#include "cellvalue.hxx"
+#include <formula/errorcodes.hxx>
+#include "editutil.hxx"
+
+template <typename TFunctor>
+auto ScCellFormat::visitInputSharedString(const ScRefCellValue& rCell, 
sal_uInt32 nFormat,
+                                          ScInterpreterContext* pContext, 
const ScDocument& rDoc,
+                                          svl::SharedStringPool& rStrPool, 
bool bFiltering,
+                                          bool bForceSystemLocale, const 
TFunctor& rOper)
+{
+    ScInterpreterContext& rContext = pContext ? *pContext : 
rDoc.GetNonThreadedContext();
+
+    switch (rCell.getType())
+    {
+        case CELLTYPE_STRING:
+        case CELLTYPE_EDIT:
+            return rOper(rCell.getSharedString(&rDoc, rStrPool));
+        case CELLTYPE_VALUE:
+            return rOper(rStrPool.intern(rContext.NFGetInputLineString(
+                rCell.getDouble(), nFormat, bFiltering, bForceSystemLocale)));
+            break;
+        case CELLTYPE_FORMULA:
+        {
+            ScFormulaCell* pFC = rCell.getFormula();
+            const FormulaError nErrCode = pFC->GetErrCode();
+            if (nErrCode != FormulaError::NONE)
+                return rOper(svl::SharedString::getEmptyString());
+            else if (pFC->IsEmptyDisplayedAsString())
+                return rOper(svl::SharedString::getEmptyString());
+            else if (pFC->IsValue())
+                return rOper(rStrPool.intern(rContext.NFGetInputLineString(
+                    pFC->GetValue(), nFormat, bFiltering, 
bForceSystemLocale)));
+            else
+                return rOper(pFC->GetString());
+        }
+        case CELLTYPE_NONE:
+        default:
+            return rOper(svl::SharedString::getEmptyString());
+    }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/inc/queryevaluator.hxx b/sc/inc/queryevaluator.hxx
index e067f92e41b1..ff086e9fa8bf 100644
--- a/sc/inc/queryevaluator.hxx
+++ b/sc/inc/queryevaluator.hxx
@@ -106,6 +106,13 @@ class ScQueryEvaluator
     std::pair<bool, bool> processEntry(SCROW nRow, SCCOL nCol, ScRefCellValue& 
aCell,
                                        const ScQueryEntry& rEntry, size_t 
nEntryIndex);
 
+    bool equalCellSharedString(const ScRefCellValue& rCell, SCROW nRow, 
SCCOLROW nField,
+                               bool bCaseSens, const svl::SharedString& 
rString);
+
+    template <typename TFunctor>
+    auto visitCellSharedString(const ScRefCellValue& rCell, SCROW nRow, SCCOL 
nCol,
+                               const TFunctor& rOper);
+
 public:
     ScQueryEvaluator(ScDocument& rDoc, const ScTable& rTab, const 
ScQueryParam& rParam,
                      ScInterpreterContext* pContext = nullptr, bool* 
pTestEqualCondition = nullptr,
diff --git a/sc/source/core/data/queryevaluator.cxx 
b/sc/source/core/data/queryevaluator.cxx
index 1534e2aa798d..98ef255946e2 100644
--- a/sc/source/core/data/queryevaluator.cxx
+++ b/sc/source/core/data/queryevaluator.cxx
@@ -21,6 +21,7 @@
 #include <queryevaluator.hxx>
 
 #include <cellform.hxx>
+#include <cellformtmpl.hxx>
 #include <cellvalue.hxx>
 #include <document.hxx>
 #include <docoptio.hxx>
@@ -325,8 +326,9 @@ OUString ScQueryEvaluator::getCellString(const 
ScRefCellValue& rCell, SCROW nRow
     }
 }
 
-svl::SharedString ScQueryEvaluator::getCellSharedString(const ScRefCellValue& 
rCell, SCROW nRow,
-                                                        SCCOL nCol)
+template <typename TFunctor>
+auto ScQueryEvaluator::visitCellSharedString(const ScRefCellValue& rCell, 
SCROW nRow, SCCOL nCol,
+                                             const TFunctor& rOper)
 {
     if (rCell.getType() == CELLTYPE_FORMULA
         && rCell.getFormula()->GetErrCode() != FormulaError::NONE)
@@ -341,22 +343,49 @@ svl::SharedString 
ScQueryEvaluator::getCellSharedString(const ScRefCellValue& rC
             assert(pos.second); // inserted
             it = pos.first;
         }
-        return it->second;
+        return rOper(it->second);
     }
     else if (rCell.getType() == CELLTYPE_STRING)
     {
-        return *rCell.getSharedString();
+        return rOper(*rCell.getSharedString());
     }
     else
     {
         sal_uInt32 nFormat
             = mpContext ? mrTab.GetNumberFormat(*mpContext, ScAddress(nCol, 
nRow, mrTab.GetTab()))
                         : mrTab.GetNumberFormat(nCol, nRow);
-        return ScCellFormat::GetInputSharedString(rCell, nFormat, mpContext, 
mrDoc, mrStrPool,
-                                                  true);
+        return ScCellFormat::visitInputSharedString(rCell, nFormat, mpContext, 
mrDoc, mrStrPool,
+                                                    true, false, rOper);
     }
 }
 
+svl::SharedString ScQueryEvaluator::getCellSharedString(const ScRefCellValue& 
rCell, SCROW nRow,
+                                                        SCCOL nCol)
+{
+    return visitCellSharedString(rCell, nRow, nCol,
+                                 [](const svl::SharedString& arg) { return 
arg; });
+}
+
+static bool equalCellSharedString(const svl::SharedString& rValueSource,
+                                  const svl::SharedString& rString, bool 
bCaseSens)
+{
+    // Fast string equality check by comparing string identifiers.
+    // This is the bFast path, all conditions should lead here on bFast == 
true.
+    if (bCaseSens)
+        return rValueSource.getData() == rString.getData();
+    return rValueSource.getDataIgnoreCase() == rString.getDataIgnoreCase();
+}
+
+bool ScQueryEvaluator::equalCellSharedString(const ScRefCellValue& rCell, 
SCROW nRow,
+                                             SCCOLROW nField, bool bCaseSens,
+                                             const svl::SharedString& rString)
+{
+    return visitCellSharedString(rCell, nRow, nField,
+                                 [&rString, bCaseSens](const 
svl::SharedString& arg) {
+                                     return ::equalCellSharedString(arg, 
rString, bCaseSens);
+                                 });
+}
+
 bool ScQueryEvaluator::isFastCompareByString(const ScQueryEntry& rEntry) const
 {
     // If this is true, then there's a fast path in compareByString() which
@@ -462,26 +491,19 @@ std::pair<bool, bool> 
ScQueryEvaluator::compareByString(const ScQueryEntry& rEnt
             }
             else
             {
-                svl::SharedString rValueSource = getCellSharedString(rCell, 
nRow, rEntry.nField);
                 if (bFast || bMatchWholeCell)
                 {
-                    // Fast string equality check by comparing string 
identifiers.
-                    // This is the bFast path, all conditions should lead here 
on bFast == true.
-                    if (mrParam.bCaseSens)
-                    {
-                        bOk = rValueSource.getData() == 
rItem.maString.getData();
-                    }
-                    else
-                    {
-                        bOk = rValueSource.getDataIgnoreCase()
-                              == rItem.maString.getDataIgnoreCase();
-                    }
+                    bOk = equalCellSharedString(rCell, nRow, rEntry.nField, 
mrParam.bCaseSens,
+                                                rItem.maString);
 
                     if (!bFast && rEntry.eOp == SC_NOT_EQUAL)
                         bOk = !bOk;
                 }
                 else
                 {
+                    svl::SharedString rValueSource
+                        = getCellSharedString(rCell, nRow, rEntry.nField);
+
                     // Where do we find a match (if at all)
                     sal_Int32 nStrPos;
 
diff --git a/sc/source/core/tool/cellform.cxx b/sc/source/core/tool/cellform.cxx
index 2447e357d32c..4b3349053fd0 100644
--- a/sc/source/core/tool/cellform.cxx
+++ b/sc/source/core/tool/cellform.cxx
@@ -18,6 +18,7 @@
  */
 
 #include <cellform.hxx>
+#include <cellformtmpl.hxx>
 
 #include <svl/numformat.hxx>
 #include <svl/sharedstring.hxx>
@@ -172,33 +173,11 @@ svl::SharedString ScCellFormat::GetInputSharedString(
     svl::SharedStringPool& rStrPool,
     bool bFiltering, bool bForceSystemLocale )
 {
-    ScInterpreterContext& rContext = pContext ? *pContext : 
rDoc.GetNonThreadedContext();
-
-    switch (rCell.getType())
-    {
-        case CELLTYPE_STRING:
-        case CELLTYPE_EDIT:
-            return rCell.getSharedString(&rDoc, rStrPool);
-        case CELLTYPE_VALUE:
-            return 
rStrPool.intern(rContext.NFGetInputLineString(rCell.getDouble(), nFormat, 
bFiltering, bForceSystemLocale));
-        break;
-        case CELLTYPE_FORMULA:
-        {
-            ScFormulaCell* pFC = rCell.getFormula();
-            const FormulaError nErrCode = pFC->GetErrCode();
-            if (nErrCode != FormulaError::NONE)
-                return svl::SharedString::getEmptyString();
-            else if (pFC->IsEmptyDisplayedAsString())
-                return svl::SharedString::getEmptyString();
-            else if (pFC->IsValue())
-                return 
rStrPool.intern(rContext.NFGetInputLineString(pFC->GetValue(), nFormat, 
bFiltering, bForceSystemLocale));
-            else
-                return pFC->GetString();
-        }
-        case CELLTYPE_NONE:
-        default:
-            return svl::SharedString::getEmptyString();
-    }
+    return visitInputSharedString(rCell, nFormat, pContext, rDoc, rStrPool,
+                                  bFiltering, bForceSystemLocale,
+            [](const svl::SharedString& arg) {
+                return arg;
+           });
 }
 
 OUString ScCellFormat::GetOutputString( ScDocument& rDoc, const ScAddress& 
rPos, const ScRefCellValue& rCell )

Reply via email to