ITEM: Add measurements for SfxItemSet usages (debug only)
I was wondering how much of that arrays of pointers to SfxPoolItems is actually used in the SfxItemSets in real office runtime, so I added code now to measure that. It does use the state of the ItemSet at destruction, so it is possible that items were added/removed which are not covered, but most cases of internal usages do not do that. I then check/sort the collected data at office shutdown, it will be printed as SAL_INFO when svl.items/vcl.items is set, so use this to see the data. This gives info about the average space utilization in different ItemSets with different sizes, also gives an insight about used ItemSet sizes and amount of their usages. Of course results differ from app to app and dependent of what is done with the office, but interestingly when using quite some files opening from all apps it toggles/normalizes to something around 20-25%... Change-Id: I3eb2f0401c39a5bdb5d1d8176e95df07be4c111a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166455 Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com> Tested-by: Jenkins
This commit is contained in:
committed by
Armin Le Grand
parent
a29d91ac40
commit
fd2aaac247
@@ -37,6 +37,7 @@ SVL_DLLPUBLIC size_t getUsedSfxItemSetCount();
|
||||
SVL_DLLPUBLIC size_t getAllocatedSfxPoolItemHolderCount();
|
||||
SVL_DLLPUBLIC size_t getUsedSfxPoolItemHolderCount();
|
||||
SVL_DLLPUBLIC void listSfxPoolItemsWithHighestUsage(sal_uInt16);
|
||||
SVL_DLLPUBLIC void listSfxItemSetUsage();
|
||||
#endif
|
||||
|
||||
// ItemSet/ItemPool helpers
|
||||
|
||||
@@ -49,9 +49,26 @@ size_t getUsedSfxItemSetCount() { return nUsedSfxItemSetCount; }
|
||||
size_t getAllocatedSfxPoolItemHolderCount() { return nAllocatedSfxPoolItemHolderCount; }
|
||||
size_t getUsedSfxPoolItemHolderCount() { return nUsedSfxPoolItemHolderCount; }
|
||||
|
||||
// <WhichID, <number of entries, typeid_name>>
|
||||
typedef std::unordered_map<sal_uInt16, std::pair<sal_uInt32, const char*>> HightestUsage;
|
||||
static HightestUsage aHightestUsage;
|
||||
|
||||
// <TotalCount, <number of entries, sum of used count>>
|
||||
typedef std::unordered_map<sal_uInt16, std::pair<sal_uInt32, sal_uInt32>> ItemArrayUsage;
|
||||
static ItemArrayUsage aItemArrayUsage;
|
||||
|
||||
static void addArrayUsage(sal_uInt16 nCount, sal_uInt16 nTotalCount)
|
||||
{
|
||||
ItemArrayUsage::iterator aHit(aItemArrayUsage.find(nTotalCount));
|
||||
if (aHit == aItemArrayUsage.end())
|
||||
{
|
||||
aItemArrayUsage.insert({nTotalCount, {1, nCount}});
|
||||
return;
|
||||
}
|
||||
aHit->second.first++;
|
||||
aHit->second.second += nCount;
|
||||
}
|
||||
|
||||
static void addUsage(const SfxPoolItem& rCandidate)
|
||||
{
|
||||
HightestUsage::iterator aHit(aHightestUsage.find(rCandidate.Which()));
|
||||
@@ -87,6 +104,42 @@ void listSfxPoolItemsWithHighestUsage(sal_uInt16 nNum)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SVL_DLLPUBLIC void listSfxItemSetUsage()
|
||||
{
|
||||
struct sorted {
|
||||
sal_uInt16 nTotalCount;
|
||||
sal_uInt32 nAppearances;
|
||||
sal_uInt32 nAllUsedCount;
|
||||
sorted(sal_uInt16 _nTotalCount, sal_uInt32 _nAppearances, sal_uInt32 _nAllUsedCount)
|
||||
: nTotalCount(_nTotalCount), nAppearances(_nAppearances), nAllUsedCount(_nAllUsedCount) {}
|
||||
bool operator<(const sorted& rDesc) const { return nTotalCount > rDesc.nTotalCount; }
|
||||
};
|
||||
std::vector<sorted> aSorted;
|
||||
aSorted.reserve(aItemArrayUsage.size());
|
||||
for (const auto& rEntry : aItemArrayUsage)
|
||||
aSorted.emplace_back(rEntry.first, rEntry.second.first, rEntry.second.second);
|
||||
std::sort(aSorted.begin(), aSorted.end());
|
||||
SAL_INFO("svl.items", "ITEM: List of " << aItemArrayUsage.size() << " SfxItemPool TotalCounts with usages:");
|
||||
double fAllFillRatePercent(0.0);
|
||||
sal_uInt32 nUsed(0);
|
||||
sal_uInt32 nAllocated(0);
|
||||
for (const auto& rEntry : aSorted)
|
||||
{
|
||||
const sal_uInt32 nAllCount(rEntry.nAppearances * rEntry.nTotalCount);
|
||||
const double fFillRatePercent(0 == nAllCount ? 0.0 : (static_cast<double>(rEntry.nAllUsedCount) / static_cast<double>(nAllCount)) * 100.0);
|
||||
SAL_INFO("svl.items",
|
||||
" TotalCount: " << rEntry.nTotalCount
|
||||
<< " Appearances: " << rEntry.nAppearances
|
||||
<< " FillRate(%): " << fFillRatePercent);
|
||||
fAllFillRatePercent += fFillRatePercent;
|
||||
nUsed += rEntry.nAllUsedCount;
|
||||
nAllocated += rEntry.nTotalCount * rEntry.nAppearances;
|
||||
}
|
||||
SAL_INFO("svl.items", " Average FillRate(%): " << fAllFillRatePercent / aItemArrayUsage.size());
|
||||
SAL_INFO("svl.items", " Used: " << nUsed << " Allocated: " << nAllocated);
|
||||
SAL_INFO("svl.items", " Average Used/Allocated(%): " << (static_cast<double>(nUsed) / static_cast<double>(nAllocated)) * 100.0);
|
||||
}
|
||||
#endif
|
||||
// NOTE: Only needed for one Item in SC (see notes below for
|
||||
// ScPatternAttr). Still keep it so that when errors
|
||||
@@ -826,6 +879,7 @@ SfxItemSet::~SfxItemSet()
|
||||
{
|
||||
#ifdef DBG_UTIL
|
||||
nAllocatedSfxItemSetCount--;
|
||||
addArrayUsage(Count(), TotalCount());
|
||||
#endif
|
||||
// cleanup items. No std::fill needed, we are done with this ItemSet.
|
||||
// the callback is not set in destructor, so no worries about that
|
||||
|
||||
@@ -211,6 +211,7 @@ Application::~Application()
|
||||
// List SfxPoolItems with highest RefCounts, these are the best
|
||||
// candidates to add a ItemInstanceManager mechanism
|
||||
listSfxPoolItemsWithHighestUsage(20);
|
||||
listSfxItemSetUsage();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user