sc/inc/column.hxx                   |    3 +-
 sc/inc/mtvelements.hxx              |    5 ++-
 sc/source/core/data/column.cxx      |    6 +++-
 sc/source/core/data/column2.cxx     |    4 --
 sc/source/core/data/column3.cxx     |    1 
 sc/source/core/data/column4.cxx     |   51 ++++++++++++++++++++++++------------
 sc/source/core/data/mtvelements.cxx |    6 ++++
 7 files changed, 53 insertions(+), 23 deletions(-)

New commits:
commit ed05777e5ad2772d5e869095547a65c7c776855f
Author:     Kohei Yoshida <[email protected]>
AuthorDate: Mon Feb 26 19:50:19 2024 -0500
Commit:     Caolán McNamara <[email protected]>
CommitDate: Thu Feb 29 09:59:54 2024 +0100

    Make ScColumn::HasCellNotes() less expensive
    
    It's essentially the same idea as checking if the column has formula cells; 
by keeping track of the block creation and deletion events to
    count the number of cell notes block instances at any given moment, and
    use that information to see if the column has any cell notes.
    
    Change-Id: I95c5186bf1f21f23f85fa10ff3c2135388949c72
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/163996
    Tested-by: Kohei Yoshida <[email protected]>
    Reviewed-by: Kohei Yoshida <[email protected]>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164006
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-by: Caolán McNamara <[email protected]>

diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 733923b0f58c..0ae88bea61bb 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -205,7 +205,8 @@ class ScColumn : protected ScColumnData
     // Sparklines
     sc::SparklineStoreType maSparklines;
 
-    size_t mnBlkCountFormula;
+    sal_uInt32 mnBlkCountFormula;
+    sal_uInt32 mnBlkCountCellNotes;
 
     SCCOL           nCol;
     SCTAB           nTab;
diff --git a/sc/inc/mtvelements.hxx b/sc/inc/mtvelements.hxx
index 156346a945ba..9a7b525fb82a 100644
--- a/sc/inc/mtvelements.hxx
+++ b/sc/inc/mtvelements.hxx
@@ -114,8 +114,9 @@ struct SparklineTraits : public mdds::mtv::default_traits
     using block_funcs = mdds::mtv::element_block_funcs<sc::sparkline_block>;
 };
 
-struct CellNodeTraits : public mdds::mtv::default_traits
+struct CellNoteTraits : public mdds::mtv::default_traits
 {
+    using event_func = CellStoreEvent;
     using block_funcs = mdds::mtv::element_block_funcs<sc::cellnote_block>;
 };
 
@@ -140,7 +141,7 @@ struct CellStoreTraits : public mdds::mtv::default_traits
 typedef mdds::mtv::soa::multi_type_vector<SparklineTraits> SparklineStoreType;
 
 /// Cell note container
-typedef mdds::mtv::soa::multi_type_vector<CellNodeTraits> CellNoteStoreType;
+typedef mdds::mtv::soa::multi_type_vector<CellNoteTraits> CellNoteStoreType;
 
 /// Broadcaster storage container
 typedef mdds::mtv::soa::multi_type_vector<BroadcasterTraits> 
BroadcasterStoreType;
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index 5bae9b7b9de7..1deffbf0adbf 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -82,15 +82,17 @@ ScNeededSizeOptions::ScNeededSizeOptions() :
 
 ScColumn::ScColumn(ScSheetLimits const & rSheetLimits) :
     maCellTextAttrs(rSheetLimits.GetMaxRowCount()),
-    maCellNotes(rSheetLimits.GetMaxRowCount()),
+    maCellNotes(sc::CellStoreEvent(this)),
     maBroadcasters(rSheetLimits.GetMaxRowCount()),
     maCells(sc::CellStoreEvent(this)),
     maSparklines(rSheetLimits.GetMaxRowCount()),
     mnBlkCountFormula(0),
+    mnBlkCountCellNotes(0),
     nCol( 0 ),
     nTab( 0 ),
     mbEmptyBroadcastersPending( false )
 {
+    maCellNotes.resize(rSheetLimits.GetMaxRowCount());
     maCells.resize(rSheetLimits.GetMaxRowCount());
 }
 
@@ -1834,7 +1836,9 @@ void ScColumn::SwapCol(ScColumn& rCol)
 
     // Swap all CellStoreEvent mdds event_func related.
     maCells.event_handler().swap(rCol.maCells.event_handler());
+    maCellNotes.event_handler().swap(rCol.maCellNotes.event_handler());
     std::swap( mnBlkCountFormula, rCol.mnBlkCountFormula);
+    std::swap(mnBlkCountCellNotes, rCol.mnBlkCountCellNotes);
 
     // notes update caption
     UpdateNoteCaptions(0, GetDoc().MaxRow());
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index 0592c97e580c..c8a0c0821889 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -2273,9 +2273,7 @@ void ScColumn::DeleteCellNotes( sc::ColumnBlockPosition& 
rBlockPos, SCROW nRow1,
 
 bool ScColumn::HasCellNotes() const
 {
-    if (maCellNotes.block_size() == 1 && maCellNotes.begin()->type == 
sc::element_type_empty)
-        return false; // all elements are empty
-    return true; // otherwise some must be notes
+    return mnBlkCountCellNotes != 0;
 }
 
 SCROW ScColumn::GetCellNotesMaxRow() const
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index 79027226387e..e515ff21e69d 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -238,6 +238,7 @@ void ScColumn::Delete( SCROW nRow )
 void ScColumn::FreeAll()
 {
     maCells.event_handler().stop();
+    maCellNotes.event_handler().stop();
 
     auto maxRowCount = GetDoc().GetMaxRowCount();
     // Keep a logical empty range of 0-rDoc.MaxRow() at all times.
diff --git a/sc/source/core/data/column4.cxx b/sc/source/core/data/column4.cxx
index 324e54be2a92..8b73d5c21518 100644
--- a/sc/source/core/data/column4.cxx
+++ b/sc/source/core/data/column4.cxx
@@ -2210,27 +2210,46 @@ void ScColumn::RestoreFromCache(SvStream& rStrm)
 
 void ScColumn::CheckIntegrity() const
 {
-    const ScColumn* pColTest = maCells.event_handler().getColumn();
+    auto checkEventHandlerColumnRef = [this](const auto& rStore, 
std::string_view pStoreName)
+    {
+        if (const ScColumn* pColTest = rStore.event_handler().getColumn(); 
pColTest != this)
+        {
+            std::ostringstream os;
+            os << pStoreName << "'s event handler references wrong column 
instance (this=" << this
+                << "; stored=" << pColTest << ")";
+            throw std::runtime_error(os.str());
+        }
+    };
 
-    if (pColTest != this)
+    auto countBlocks = [](const auto& rStore, mdds::mtv::element_t nBlockType)
     {
-        std::ostringstream os;
-        os << "cell store's event handler references wrong column instance 
(this=" << this
-            << "; stored=" << pColTest << ")";
-        throw std::runtime_error(os.str());
-    }
+        std::size_t nCount = std::count_if(rStore.cbegin(), rStore.cend(),
+            [nBlockType](const auto& blk) { return blk.type == nBlockType; }
+        );
 
-    size_t nCount = std::count_if(maCells.cbegin(), maCells.cend(),
-        [](const auto& blk) { return blk.type == sc::element_type_formula; }
-    );
+        return nCount;
+    };
 
-    if (mnBlkCountFormula != nCount)
+    auto checkCachedBlockCount = [countBlocks](
+        const auto& rStore, mdds::mtv::element_t nBlockType, std::size_t 
nCachedBlkCount,
+        std::string_view pName)
     {
-        std::ostringstream os;
-        os << "incorrect cached formula block count (expected=" << nCount << 
"; actual="
-            << mnBlkCountFormula << ")";
-        throw std::runtime_error(os.str());
-    }
+        std::size_t nCount = countBlocks(rStore, nBlockType);
+
+        if (nCachedBlkCount != nCount)
+        {
+            std::ostringstream os;
+            os << "incorrect cached " << pName << " block count (expected=" << 
nCount << "; actual="
+                << nCachedBlkCount << ")";
+            throw std::runtime_error(os.str());
+        }
+    };
+
+    checkEventHandlerColumnRef(maCells, "cell store");
+    checkEventHandlerColumnRef(maCellNotes, "cell-note store");
+
+    checkCachedBlockCount(maCells, sc::element_type_formula, 
mnBlkCountFormula, "formula");
+    checkCachedBlockCount(maCellNotes, sc::element_type_cellnote, 
mnBlkCountCellNotes, "cell note");
 }
 
 void ScColumn::CollectBroadcasterState(sc::BroadcasterState& rState) const
diff --git a/sc/source/core/data/mtvelements.cxx 
b/sc/source/core/data/mtvelements.cxx
index 9bc28056bd79..9f5399701d31 100644
--- a/sc/source/core/data/mtvelements.cxx
+++ b/sc/source/core/data/mtvelements.cxx
@@ -31,6 +31,9 @@ void CellStoreEvent::element_block_acquired(const 
mdds::mtv::base_element_block*
         case sc::element_type_formula:
             ++mpCol->mnBlkCountFormula;
             break;
+        case sc::element_type_cellnote:
+            ++mpCol->mnBlkCountCellNotes;
+            break;
         default:
             ;
     }
@@ -46,6 +49,9 @@ void CellStoreEvent::element_block_released(const 
mdds::mtv::base_element_block*
         case sc::element_type_formula:
             --mpCol->mnBlkCountFormula;
             break;
+        case sc::element_type_cellnote:
+            --mpCol->mnBlkCountCellNotes;
+            break;
         default:
             ;
     }

Reply via email to