sc/inc/column.hxx                          |    2 -
 sc/inc/interpretercontext.hxx              |   47 ++++++++++++++++-------
 sc/inc/patattr.hxx                         |    2 +
 sc/source/core/data/patattr.cxx            |   11 +++++
 sc/source/core/tool/interpretercontext.cxx |   57 ++++++++++++++++++++++++-----
 5 files changed, 94 insertions(+), 25 deletions(-)

New commits:
commit e310c8714cba16f592d59596caadf39bd01b61d0
Author:     Caolán McNamara <caolan.mcnam...@collabora.com>
AuthorDate: Thu Feb 29 20:09:09 2024 +0000
Commit:     Adolfo Jayme Barrientos <fit...@ubuntu.com>
CommitDate: Mon Apr 15 05:55:54 2024 +0200

    avoid SvNumberFormatter lock in formula-group-threading
    
    keep a per-interpret-thread cache of the SvNumberFormatter
    mapping while formula-group-threading, this is similar to:
    
    commit c2d8341ee392949274b901abfd44d9645d2e4e36
    Date:   Tue Oct 15 08:32:22 2019 +0530
    
        Cache last used number-format-type in interpreter-context
    
    Change-Id: Ie99807eaf2f3260cec357f9d66307df0a69826e9
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164227
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    (cherry picked from commit 2c3605405225de4b850064cf25b15cd64be1409b)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/165748
    Reviewed-by: Adolfo Jayme Barrientos <fit...@ubuntu.com>

diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 733923b0f58c..69850197bdaa 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -984,7 +984,7 @@ inline const SfxPoolItem& ScColumnData::GetAttr( SCROW 
nRow, sal_uInt16 nWhich,
 
 inline sal_uInt32 ScColumnData::GetNumberFormat( const ScInterpreterContext& 
rContext, SCROW nRow ) const
 {
-    return pAttrArray->GetPattern( nRow )->GetNumberFormat( 
rContext.GetFormatTable() );
+    return pAttrArray->GetPattern( nRow )->GetNumberFormat( rContext );
 }
 
 inline void ScColumn::AddCondFormat( SCROW nStartRow, SCROW nEndRow, 
sal_uInt32 nIndex )
diff --git a/sc/inc/interpretercontext.hxx b/sc/inc/interpretercontext.hxx
index 39d528cb6ca9..11e2c6990c8e 100644
--- a/sc/inc/interpretercontext.hxx
+++ b/sc/inc/interpretercontext.hxx
@@ -9,8 +9,11 @@
 
 #pragma once
 
+#include <array>
 #include <vector>
 #include <memory>
+#include <i18nlangtag/lang.h>
+#include <svl/numformat.hxx>
 #include "types.hxx"
 
 namespace formula
@@ -34,20 +37,6 @@ struct DelayedSetNumberFormat
     sal_uInt32 mnNumberFormat;
 };
 
-struct NFIndexAndFmtType
-{
-    sal_uInt32 nIndex;
-    SvNumFormatType eType : 16;
-    bool bIsValid : 1;
-
-    NFIndexAndFmtType()
-        : nIndex(0)
-        , eType(static_cast<SvNumFormatType>(0))
-        , bIsValid(false)
-    {
-    }
-};
-
 class ScInterpreterContextPool;
 
 struct ScInterpreterContext
@@ -77,6 +66,8 @@ struct ScInterpreterContext
 
     SvNumFormatType GetNumberFormatType(sal_uInt32 nFIndex) const;
 
+    sal_uInt32 GetFormatForLanguageIfBuiltIn(sal_uInt32 nFormat, LanguageType 
eLnge) const;
+
 private:
     friend class ScInterpreterContextPool;
     void ResetTokens();
@@ -85,7 +76,33 @@ private:
     void ClearLookupCache(const ScDocument* pDoc);
     void initFormatTable();
     SvNumberFormatter* mpFormatter;
-    mutable NFIndexAndFmtType maNFTypeCache;
+
+    // Some temp caches of the 4 most recent results from NumberFormatting
+    // lookups.
+    struct NFBuiltIn
+    {
+        sal_uInt64 nKey;
+        sal_uInt32 nFormat;
+        NFBuiltIn()
+            : nKey(SAL_MAX_UINT64)
+            , nFormat(SAL_MAX_UINT32)
+        {
+        }
+    };
+    // from format+lang to builtin format
+    mutable std::array<NFBuiltIn, 4> maNFBuiltInCache;
+    struct NFType
+    {
+        sal_uInt32 nKey;
+        SvNumFormatType eType;
+        NFType()
+            : nKey(SAL_MAX_UINT32)
+            , eType(SvNumFormatType::ALL)
+        {
+        }
+    };
+    // from format index to type
+    mutable std::array<NFType, 4> maNFTypeCache;
 };
 
 class ScThreadedInterpreterContextGetterGuard;
diff --git a/sc/inc/patattr.hxx b/sc/inc/patattr.hxx
index d6536551f965..e4b149516c0f 100644
--- a/sc/inc/patattr.hxx
+++ b/sc/inc/patattr.hxx
@@ -31,6 +31,7 @@
 
 namespace vcl { class Font; }
 namespace model { class ComplexColor; }
+struct ScInterpreterContext;
 class OutputDevice;
 class Fraction;
 class ScStyleSheet;
@@ -171,6 +172,7 @@ public:
     bool                    IsSymbolFont() const;
 
     sal_uInt32              GetNumberFormat( SvNumberFormatter* ) const;
+    sal_uInt32              GetNumberFormat( const ScInterpreterContext& 
rContext ) const;
     sal_uInt32              GetNumberFormat( SvNumberFormatter* pFormatter,
                                              const SfxItemSet* pCondSet ) 
const;
 
diff --git a/sc/source/core/data/patattr.cxx b/sc/source/core/data/patattr.cxx
index 4bb79828da13..f5db8533cfe0 100644
--- a/sc/source/core/data/patattr.cxx
+++ b/sc/source/core/data/patattr.cxx
@@ -1412,6 +1412,17 @@ sal_uInt32 ScPatternAttr::GetNumberFormat( 
SvNumberFormatter* pFormatter ) const
     return nFormat;
 }
 
+sal_uInt32 ScPatternAttr::GetNumberFormat( const ScInterpreterContext& 
rContext ) const
+{
+    sal_uInt32 nFormat = getNumberFormatKey(GetItemSet());
+    LanguageType eLang = getLanguageType(GetItemSet());
+    if ( nFormat < SV_COUNTRY_LANGUAGE_OFFSET && eLang == LANGUAGE_SYSTEM )
+        ;       // it remains as it is
+    else
+        nFormat = rContext.GetFormatForLanguageIfBuiltIn( nFormat, eLang );
+    return nFormat;
+}
+
 // the same if conditional formatting is in play:
 
 sal_uInt32 ScPatternAttr::GetNumberFormat( SvNumberFormatter* pFormatter,
diff --git a/sc/source/core/tool/interpretercontext.cxx 
b/sc/source/core/tool/interpretercontext.cxx
index deb6f6d0ed5b..235d42d03fd6 100644
--- a/sc/source/core/tool/interpretercontext.cxx
+++ b/sc/source/core/tool/interpretercontext.cxx
@@ -58,7 +58,14 @@ void ScInterpreterContext::SetDocAndFormatter(const 
ScDocument& rDoc, SvNumberFo
         mxScLookupCache.reset();
         mpDoc = &rDoc;
     }
-    mpFormatter = pFormatter;
+    if (mpFormatter != pFormatter)
+    {
+        mpFormatter = pFormatter;
+
+        // drop cache
+        std::fill(maNFBuiltInCache.begin(), maNFBuiltInCache.end(), 
NFBuiltIn());
+        std::fill(maNFTypeCache.begin(), maNFTypeCache.end(), NFType());
+    }
 }
 
 void ScInterpreterContext::initFormatTable()
@@ -87,15 +94,47 @@ SvNumFormatType 
ScInterpreterContext::GetNumberFormatType(sal_uInt32 nFIndex) co
         return mpFormatter->GetType(nFIndex);
     }
 
-    if (maNFTypeCache.bIsValid && maNFTypeCache.nIndex == nFIndex)
-    {
-        return maNFTypeCache.eType;
-    }
+    auto aFind = std::find_if(maNFTypeCache.begin(), maNFTypeCache.end(),
+                              [nFIndex](const NFType& e) { return e.nKey == 
nFIndex; });
+    if (aFind != maNFTypeCache.end())
+        return aFind->eType;
+
+    SvNumFormatType eType = mpFormatter->GetType(nFIndex);
+
+    std::move_backward(maNFTypeCache.begin(),
+                       std::next(maNFTypeCache.begin(), maNFTypeCache.size() - 
1),
+                       maNFTypeCache.end());
+    maNFTypeCache[0].nKey = nFIndex;
+    maNFTypeCache[0].eType = eType;
+
+    return eType;
+}
+
+sal_uInt32 ScInterpreterContext::GetFormatForLanguageIfBuiltIn(sal_uInt32 
nFormat,
+                                                               LanguageType 
eLnge) const
+{
+    if (!mpFormatter)
+        return nFormat;
+
+    if (!mpDoc->IsThreadedGroupCalcInProgress())
+        return mpFormatter->GetFormatForLanguageIfBuiltIn(nFormat, eLnge);
+
+    sal_uInt64 nKey = (static_cast<sal_uInt64>(nFormat) << 32) | eLnge.get();
+
+    auto aFind = std::find_if(maNFBuiltInCache.begin(), maNFBuiltInCache.end(),
+                              [nKey](const NFBuiltIn& e) { return e.nKey == 
nKey; });
+    if (aFind != maNFBuiltInCache.end())
+        return aFind->nFormat;
+
+    nFormat = mpFormatter->GetFormatForLanguageIfBuiltIn(nFormat, eLnge);
+
+    std::move_backward(maNFBuiltInCache.begin(),
+                       std::next(maNFBuiltInCache.begin(), 
maNFBuiltInCache.size() - 1),
+                       maNFBuiltInCache.end());
+    maNFBuiltInCache[0].nKey = nKey;
+    maNFBuiltInCache[0].nFormat = nFormat;
 
-    maNFTypeCache.nIndex = nFIndex;
-    maNFTypeCache.eType = mpFormatter->GetType(nFIndex);
-    maNFTypeCache.bIsValid = true;
-    return maNFTypeCache.eType;
+    return nFormat;
 }
 
 /* ScInterpreterContextPool */

Reply via email to