diff options
author | Caolán McNamara <caolan.mcnamara@collabora.com> | 2024-02-29 20:09:09 +0000 |
---|---|---|
committer | Caolán McNamara <caolan.mcnamara@collabora.com> | 2024-03-02 21:54:34 +0100 |
commit | 2c3605405225de4b850064cf25b15cd64be1409b (patch) | |
tree | 7a24b1cc1fdd42ae83012779777bc3389436eadd | |
parent | 4f2704920c697e8a6f053de52439dbcd49a16ce3 (diff) |
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.mcnamara@collabora.com>
-rw-r--r-- | sc/inc/column.hxx | 2 | ||||
-rw-r--r-- | sc/inc/interpretercontext.hxx | 40 | ||||
-rw-r--r-- | sc/inc/patattr.hxx | 2 | ||||
-rw-r--r-- | sc/source/core/data/patattr.cxx | 11 | ||||
-rw-r--r-- | sc/source/core/tool/interpretercontext.cxx | 39 |
5 files changed, 68 insertions, 26 deletions
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index 306d7d28de3f..0aa812f038a2 100644 --- a/sc/inc/column.hxx +++ b/sc/inc/column.hxx @@ -986,7 +986,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..c46f00395cc0 100644 --- a/sc/inc/interpretercontext.hxx +++ b/sc/inc/interpretercontext.hxx @@ -11,6 +11,8 @@ #include <vector> #include <memory> +#include <i18nlangtag/lang.h> +#include <o3tl/sorted_vector.hxx> #include "types.hxx" namespace formula @@ -34,20 +36,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 +65,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 +75,27 @@ private: void ClearLookupCache(const ScDocument* pDoc); void initFormatTable(); SvNumberFormatter* mpFormatter; - mutable NFIndexAndFmtType maNFTypeCache; + + template <typename T> struct CompareKey + { + bool operator()(const T& lhs, const T& rhs) const { return lhs.nKey < rhs.nKey; } + }; + + struct NFType + { + sal_uInt32 nKey; + mutable SvNumFormatType eType; + }; + // map from format index to type + mutable o3tl::sorted_vector<NFType, CompareKey<NFType>> maNFTypeCache; + + struct NFBuiltIn + { + sal_uInt64 nKey; + mutable sal_uInt32 nFormat; + }; + // map from format+lang to builtin format + mutable o3tl::sorted_vector<NFBuiltIn, CompareKey<NFBuiltIn>> maNFBuiltInCache; }; class ScThreadedInterpreterContextGetterGuard; diff --git a/sc/inc/patattr.hxx b/sc/inc/patattr.hxx index 3c790c7637e3..bbb55b5a309f 100644 --- a/sc/inc/patattr.hxx +++ b/sc/inc/patattr.hxx @@ -32,6 +32,7 @@ namespace vcl { class Font; } namespace model { class ComplexColor; } +struct ScInterpreterContext; class OutputDevice; class Fraction; class ScStyleSheet; @@ -237,6 +238,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 59f9fa1866b4..95823cee9473 100644 --- a/sc/source/core/data/patattr.cxx +++ b/sc/source/core/data/patattr.cxx @@ -1652,6 +1652,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..03d5036b6e63 100644 --- a/sc/source/core/tool/interpretercontext.cxx +++ b/sc/source/core/tool/interpretercontext.cxx @@ -83,19 +83,38 @@ void ScInterpreterContext::ClearLookupCache(const ScDocument* pDoc) SvNumFormatType ScInterpreterContext::GetNumberFormatType(sal_uInt32 nFIndex) const { if (!mpDoc->IsThreadedGroupCalcInProgress()) - { return mpFormatter->GetType(nFIndex); - } - if (maNFTypeCache.bIsValid && maNFTypeCache.nIndex == nFIndex) - { - return maNFTypeCache.eType; - } + // Search/update cache by attempting to find nFIndex by inserting a new entry + auto result = maNFTypeCache.insert(NFType{ nFIndex, SvNumFormatType::ALL }); + if (!result.second) // already exists, so return that SvNumFormatType + return result.first->eType; - maNFTypeCache.nIndex = nFIndex; - maNFTypeCache.eType = mpFormatter->GetType(nFIndex); - maNFTypeCache.bIsValid = true; - return maNFTypeCache.eType; + // Didn't exist, overwrite the placeholder SvNumFormatType::ALL with the real type + SvNumFormatType eType = mpFormatter->GetType(nFIndex); + result.first->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(); + // Search/update cache by attempting to find nFormat+eLnge by inserting a new entry + auto result = maNFBuiltInCache.insert(NFBuiltIn{ nKey, 0 }); + if (!result.second) // already exists, so return that dest Format + return result.first->nFormat; + + // Didn't exist, overwrite the placeholder zero with the real format + nFormat = mpFormatter->GetFormatForLanguageIfBuiltIn(nFormat, eLnge); + result.first->nFormat = nFormat; + return nFormat; } /* ScInterpreterContextPool */ |