summaryrefslogtreecommitdiff
path: root/include/svl
diff options
context:
space:
mode:
authorNoel Grandin <noelgrandin@gmail.com>2021-07-10 10:19:28 +0200
committerNoel Grandin <noel.grandin@collabora.co.uk>2021-07-15 14:41:13 +0200
commit5d0a231b29dfd4d587c7a4d1bbda6a511f94ec77 (patch)
treeebc1d470fd891fe0f9e68a002055c4d3a8dd4884 /include/svl
parentdf9ca514d4e9ea87bbf0a96d99181ed8965cd45a (diff)
WhichRangesContainer, reduce malloc in SfxItemSet
SfxItemSet shows up in perf profiles frequently, and the hottest part is the malloc of the two arrays we need. But most of the time, one of those arrays is a compile-time constant. So this change introduces (*) WhichRangesContainer, which manages whether the SfxItemSet owns the array it points at or not. (*) a static const member in svl::Items (idea from mkaganski) to store the data. Change-Id: Icb8cdbc4d54fd76739565c575e16a744515e5355 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/118703 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com> Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Diffstat (limited to 'include/svl')
-rw-r--r--include/svl/itempool.hxx5
-rw-r--r--include/svl/itemset.hxx52
-rw-r--r--include/svl/whichranges.hxx74
-rw-r--r--include/svl/whiter.hxx7
4 files changed, 116 insertions, 22 deletions
diff --git a/include/svl/itempool.hxx b/include/svl/itempool.hxx
index 0ff1c8d4b27a..8d1f2324363b 100644
--- a/include/svl/itempool.hxx
+++ b/include/svl/itempool.hxx
@@ -23,6 +23,7 @@
#include <svl/poolitem.hxx>
#include <svl/svldllapi.h>
#include <svl/typedwhich.hxx>
+#include <svl/whichranges.hxx>
#include <memory>
#include <vector>
#include <o3tl/sorted_vector.hxx>
@@ -63,8 +64,8 @@ private:
public:
// for default SfxItemSet::CTOR, set default WhichRanges
- void FillItemIdRanges_Impl( std::unique_ptr<sal_uInt16[]>& pWhichRanges ) const;
- const sal_uInt16* GetFrozenIdRanges() const;
+ void FillItemIdRanges_Impl( WhichRangesContainer& pWhichRanges ) const;
+ const WhichRangesContainer & GetFrozenIdRanges() const;
protected:
static inline void ClearRefCount(SfxPoolItem& rItem);
diff --git a/include/svl/itemset.hxx b/include/svl/itemset.hxx
index 7c85e7534f59..efae21b3be61 100644
--- a/include/svl/itemset.hxx
+++ b/include/svl/itemset.hxx
@@ -32,6 +32,7 @@
#include <svl/svldllapi.h>
#include <svl/poolitem.hxx>
#include <svl/typedwhich.hxx>
+#include <svl/whichranges.hxx>
class SfxItemPool;
@@ -84,7 +85,12 @@ constexpr std::size_t rangesSize()
}
-template<sal_uInt16... WIDs> struct Items {};
+template<sal_uInt16... WIDs> struct Items
+{
+ // This is passed to WhichRangesContainer so we can avoid needing to malloc()
+ // for compile-time data.
+ static constexpr std::array<sal_uInt16, sizeof...(WIDs)> value = { { WIDs... } };
+};
}
@@ -96,18 +102,18 @@ class SAL_WARN_UNUSED SVL_DLLPUBLIC SfxItemSet
const SfxItemSet* m_pParent; ///< derivation
std::unique_ptr<SfxPoolItem const*[]>
m_pItems; ///< array of items
- sal_uInt16* m_pWhichRanges; ///< array of Which Ranges
+ WhichRangesContainer m_pWhichRanges; ///< array of Which Ranges
sal_uInt16 m_nCount; ///< number of items
friend class SfxItemPoolCache;
friend class SfxAllItemSet;
private:
- SVL_DLLPRIVATE sal_uInt16 InitRanges_Impl(const sal_uInt16 *nWhichPairTable);
+ SVL_DLLPRIVATE void RecreateRanges_Impl(const WhichRangesContainer& pNewRanges);
- SfxItemSet(
- SfxItemPool & pool, std::initializer_list<sal_uInt16> wids,
- std::size_t items);
+ SfxItemSet( SfxItemPool & pool, const WhichRangesContainer& wids, std::size_t items );
+ SfxItemSet( SfxItemPool & pool, WhichRangesContainer&& wids, std::size_t items );
+ SfxItemSet( SfxItemPool & pool, std::initializer_list<sal_uInt16> wids, std::size_t items );
public:
SfxPoolItem const** GetItems_Impl() const { return m_pItems.get(); }
@@ -123,21 +129,32 @@ protected:
virtual const SfxPoolItem* PutImpl( const SfxPoolItem&, sal_uInt16 nWhich, bool bPassingOwnership );
+ /** special constructor for SfxAllItemSet */
+ enum class SfxAllItemSetFlag { Flag };
+ SfxItemSet( SfxItemPool&, SfxAllItemSetFlag );
+
public:
struct Pair { sal_uInt16 wid1, wid2; };
+ SfxItemSet( const SfxItemSet& );
+ SfxItemSet( SfxItemSet&& ) noexcept;
+ SfxItemSet( SfxItemPool& );
+ SfxItemSet( SfxItemPool&, const WhichRangesContainer& ranges );
+ SfxItemSet( SfxItemPool&, WhichRangesContainer&& ranges );
- SfxItemSet( const SfxItemSet& );
- SfxItemSet( SfxItemSet&& ) noexcept;
+ SfxItemSet( SfxItemPool& rPool, sal_uInt16 nWhichStart, sal_uInt16 nWhichEnd )
+ : SfxItemSet(rPool, WhichRangesContainer(nWhichStart, nWhichEnd)) {}
- SfxItemSet( SfxItemPool&);
- template<sal_uInt16... WIDs> SfxItemSet(
+ template<sal_uInt16... WIDs>
+ SfxItemSet(
typename std::enable_if<
svl::detail::validRanges<WIDs...>(), SfxItemPool &>::type pool,
- svl::Items<WIDs...>):
- SfxItemSet(pool, {WIDs...}, svl::detail::rangesSize<WIDs...>()) {}
- SfxItemSet( SfxItemPool&, std::initializer_list<Pair> wids );
- SfxItemSet( SfxItemPool&, const sal_uInt16* nWhichPairTable );
- virtual ~SfxItemSet();
+ svl::Items<WIDs...>)
+ : SfxItemSet(pool, WhichRangesContainer(svl::Items<WIDs...>::value), svl::detail::rangesSize<WIDs...>()) {}
+
+ SfxItemSet( SfxItemPool&, std::initializer_list<Pair> wids );
+ SfxItemSet( SfxItemPool&, const sal_uInt16* nWhichPairTable );
+
+ virtual ~SfxItemSet();
virtual std::unique_ptr<SfxItemSet> Clone(bool bItems = true, SfxItemPool *pToPool = nullptr) const;
virtual SfxItemSet CloneAsValue(bool bItems = true, SfxItemPool *pToPool = nullptr) const;
@@ -231,8 +248,9 @@ public:
void MergeValue( const SfxPoolItem& rItem, bool bOverwriteDefaults = false );
SfxItemPool* GetPool() const { return m_pPool; }
- const sal_uInt16* GetRanges() const { return m_pWhichRanges; }
- void SetRanges( const sal_uInt16 *pRanges );
+ const WhichRangesContainer & GetRanges() const { return m_pWhichRanges; }
+ void SetRanges( const WhichRangesContainer& );
+ void SetRanges( WhichRangesContainer&& );
void MergeRange( sal_uInt16 nFrom, sal_uInt16 nTo );
const SfxItemSet* GetParent() const { return m_pParent; }
diff --git a/include/svl/whichranges.hxx b/include/svl/whichranges.hxx
new file mode 100644
index 000000000000..b1e87bba38b4
--- /dev/null
+++ b/include/svl/whichranges.hxx
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * 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/.
+ */
+#pragma once
+
+#include <sal/config.h>
+#include <sal/types.h>
+#include <svl/svldllapi.h>
+#include <array>
+#include <memory>
+#include <cassert>
+
+typedef std::pair<sal_uInt16, sal_uInt16> WhichPair;
+
+/**
+ * Most of the time, the which ranges we point at are a compile-time literal.
+ * So we take advantage of that, and avoid the cost of allocating our own array and copying into it.
+ */
+struct SVL_DLLPUBLIC WhichRangesContainer
+{
+ using const_iterator = WhichPair const*;
+
+ WhichPair const* m_pairs = nullptr;
+ sal_Int32 m_size = 0;
+ /** if true, we allocated and need to delete the pairs, if not, we are pointing
+ * at a global const literal */
+ bool m_bOwnRanges = false;
+
+ WhichRangesContainer() {}
+
+ WhichRangesContainer(std::unique_ptr<WhichPair[]> wids, sal_Int32 nSize)
+ : m_pairs(wids.release())
+ , m_size(nSize)
+ , m_bOwnRanges(true)
+ {
+ }
+ template <std::size_t N>
+ WhichRangesContainer(const std::array<sal_uInt16, N>& ranges)
+ : m_pairs(reinterpret_cast<const WhichPair*>(ranges.data()))
+ , m_size(static_cast<sal_Int32>(N / 2))
+ , m_bOwnRanges(false)
+ {
+ }
+ WhichRangesContainer(const WhichPair* wids, sal_Int32 nSize);
+ WhichRangesContainer(sal_uInt16 nWhichStart, sal_uInt16 nWhichEnd);
+ WhichRangesContainer(WhichRangesContainer const& other) { operator=(other); }
+ WhichRangesContainer(WhichRangesContainer&& other);
+ ~WhichRangesContainer();
+
+ WhichRangesContainer& operator=(WhichRangesContainer&& other);
+ WhichRangesContainer& operator=(WhichRangesContainer const& other);
+
+ bool operator==(WhichRangesContainer const& other) const;
+ const_iterator begin() const noexcept { return m_pairs; }
+ const_iterator end() const noexcept { return begin() + size(); }
+ bool empty() const noexcept { return m_size == 0; }
+ sal_Int32 size() const noexcept { return m_size; }
+ WhichPair const& operator[](sal_Int32 idx) const noexcept
+ {
+ assert(idx >= 0 && idx < size() && "index out of range");
+ return m_pairs[idx];
+ }
+ void reset();
+
+ // Adds a range to which ranges, keeping the ranges in valid state (sorted, non-overlapping)
+ WhichRangesContainer MergeRange(sal_uInt16 nFrom, sal_uInt16 nTo) const;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/include/svl/whiter.hxx b/include/svl/whiter.hxx
index be584fc23911..c4a49a06b622 100644
--- a/include/svl/whiter.hxx
+++ b/include/svl/whiter.hxx
@@ -20,19 +20,20 @@
#define INCLUDED_SVL_WHITER_HXX
#include <svl/svldllapi.h>
+#include <svl/whichranges.hxx>
class SfxItemSet;
class SVL_DLLPUBLIC SfxWhichIter
{
- const sal_uInt16* const pStart;
- const sal_uInt16* pRanges;
+ const WhichRangesContainer& pStart;
+ const WhichPair* pRanges;
sal_uInt16 nOffset;
public:
SfxWhichIter(const SfxItemSet& rSet);
- sal_uInt16 GetCurWhich() const { return pRanges[0] + nOffset; }
+ sal_uInt16 GetCurWhich() const;
sal_uInt16 NextWhich();
sal_uInt16 FirstWhich();
};