mirror of
https://github.com/LibreOffice/core.git
synced 2025-07-23 04:42:03 +00:00
use a different memory allocation strategy for caches
redirect cache related allocations to the same place to attempt to put them in separate pages from other allocations to release that cache memory back to OS. Change-Id: I384658a3d652e668095b69e5a62eae5b972b5857 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/187282 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolan.mcnamara@collabora.com>
This commit is contained in:
@ -8,11 +8,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_O3TL_LRU_MAP_HXX
|
||||
#define INCLUDED_O3TL_LRU_MAP_HXX
|
||||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
#include <list>
|
||||
#include <version>
|
||||
#if defined __cpp_lib_memory_resource
|
||||
#include <memory_resource>
|
||||
#endif
|
||||
#include <unordered_map>
|
||||
#include <cstddef>
|
||||
|
||||
@ -67,11 +70,19 @@ public:
|
||||
typedef typename std::pair<Key, Value> key_value_pair_t;
|
||||
|
||||
private:
|
||||
#if defined __cpp_lib_memory_resource
|
||||
typedef std::pmr::list<key_value_pair_t> list_t;
|
||||
#else
|
||||
typedef std::list<key_value_pair_t> list_t;
|
||||
#endif
|
||||
typedef typename list_t::iterator list_iterator_t;
|
||||
typedef typename list_t::const_iterator list_const_iterator_t;
|
||||
|
||||
#if defined __cpp_lib_memory_resource
|
||||
typedef std::pmr::unordered_map<Key, list_iterator_t, KeyHash, KeyEqual> map_t;
|
||||
#else
|
||||
typedef std::unordered_map<Key, list_iterator_t, KeyHash, KeyEqual> map_t;
|
||||
#endif
|
||||
typedef typename map_t::iterator map_iterator_t;
|
||||
typedef typename map_t::const_iterator map_const_iterator_t;
|
||||
|
||||
@ -169,13 +180,22 @@ public:
|
||||
{
|
||||
assert(mMaxSize > 0);
|
||||
}
|
||||
#if defined __cpp_lib_memory_resource
|
||||
lru_map(size_t nMaxSize, std::pmr::memory_resource* r)
|
||||
: mLruList(r)
|
||||
, mLruMap(r)
|
||||
, mMaxSize(nMaxSize)
|
||||
{
|
||||
assert(mMaxSize > 0);
|
||||
}
|
||||
#endif
|
||||
~lru_map()
|
||||
{
|
||||
clearSize();
|
||||
// Some code .e.g. SalBitmap likes to remove itself from a cache during it's destructor, which means we
|
||||
// get calls into lru_map while we are in destruction, so use the swap-and-clear idiom to avoid those problems.
|
||||
mLruMap.clear();
|
||||
list_t().swap(mLruList);
|
||||
list_t(mLruList.get_allocator()).swap(mLruList);
|
||||
}
|
||||
|
||||
void setMaxSize(size_t nMaxSize)
|
||||
@ -286,12 +306,10 @@ public:
|
||||
void clear()
|
||||
{
|
||||
clearSize();
|
||||
mLruMap.clear();
|
||||
mLruList.clear();
|
||||
map_t(mLruMap.get_allocator()).swap(mLruMap);
|
||||
list_t(mLruList.get_allocator()).swap(mLruList);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* INCLUDED_O3TL_LRU_MAP_HXX */
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
|
@ -8,6 +8,7 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <bit>
|
||||
#include <stdexcept>
|
||||
#include <o3tl/concepts.hxx>
|
||||
|
||||
@ -40,6 +41,12 @@ constexpr T convertToHex(U cHigh, U cLow)
|
||||
return (o3tl::convertToHex<T>(cHigh) << 4) | o3tl::convertToHex<T>(cLow);
|
||||
}
|
||||
|
||||
template <o3tl::integral T>
|
||||
constexpr unsigned int number_of_bits(T x)
|
||||
{
|
||||
return sizeof(T) * 8 - std::countl_zero(x);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
|
@ -10,6 +10,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <vcl/dllapi.h>
|
||||
#include <rtl/ustring.hxx>
|
||||
#include <version>
|
||||
#if defined __cpp_lib_memory_resource
|
||||
#include <memory_resource>
|
||||
#endif
|
||||
|
||||
#if defined(__COVERITY__)
|
||||
#define THREAD_UNSAFE_DUMP_BEGIN \
|
||||
@ -33,8 +38,13 @@ protected:
|
||||
virtual ~CacheOwner();
|
||||
|
||||
public:
|
||||
virtual void dropCaches() = 0;
|
||||
// returns true if cache no longer uses GetMemoryResource
|
||||
virtual bool dropCaches() = 0;
|
||||
virtual void dumpState(rtl::OStringBuffer& rState) = 0;
|
||||
virtual OUString getCacheName() const = 0;
|
||||
#if defined __cpp_lib_memory_resource
|
||||
static std::pmr::memory_resource& GetMemoryResource();
|
||||
#endif
|
||||
};
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
|
||||
|
@ -69,7 +69,11 @@ public:
|
||||
|
||||
static SalLayoutGlyphsCache* self();
|
||||
SalLayoutGlyphsCache(int size) // needs to be public for tools::DeleteOnDeinit
|
||||
#if defined __cpp_lib_memory_resource
|
||||
: mCachedGlyphs(size, &GetMemoryResource())
|
||||
#else
|
||||
: mCachedGlyphs(size)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
@ -96,7 +100,8 @@ public:
|
||||
};
|
||||
|
||||
private:
|
||||
virtual void dropCaches() override;
|
||||
virtual OUString getCacheName() const override;
|
||||
virtual bool dropCaches() override;
|
||||
virtual void dumpState(rtl::OStringBuffer& rState) override;
|
||||
|
||||
struct CachedGlyphsHash
|
||||
|
@ -232,10 +232,16 @@ struct PropertySetInfoCache : public CacheOwner
|
||||
}
|
||||
|
||||
private:
|
||||
virtual void dropCaches() override
|
||||
virtual OUString getCacheName() const override
|
||||
{
|
||||
return "PropertySetInfoCache";
|
||||
}
|
||||
|
||||
virtual bool dropCaches() override
|
||||
{
|
||||
std::unique_lock l(gCacheMutex);
|
||||
gCacheMap.clear();
|
||||
map_t(gCacheMap.get_allocator()).swap(gCacheMap);
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void dumpState(rtl::OStringBuffer& rState) override
|
||||
@ -247,7 +253,8 @@ private:
|
||||
}
|
||||
|
||||
std::mutex gCacheMutex;
|
||||
std::unordered_map<uno::Reference<beans::XPropertySetInfo>, uno::Reference<beans::XPropertySetInfo>> gCacheMap;
|
||||
typedef std::unordered_map<uno::Reference<beans::XPropertySetInfo>, uno::Reference<beans::XPropertySetInfo>> map_t;
|
||||
map_t gCacheMap;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -85,15 +85,26 @@ class SpellCheckContext::SpellCheckCache : public CacheOwner
|
||||
}
|
||||
};
|
||||
|
||||
#if defined __cpp_lib_memory_resource
|
||||
typedef std::pmr::unordered_map<CellPos, std::unique_ptr<MisspellRangesVec>, CellPos::Hash> CellMapType;
|
||||
typedef std::pmr::unordered_map<LangSharedString, std::unique_ptr<MisspellRangesVec>, LangSharedString::Hash> SharedStringMapType;
|
||||
#else
|
||||
typedef std::unordered_map<CellPos, std::unique_ptr<MisspellRangesVec>, CellPos::Hash> CellMapType;
|
||||
typedef std::unordered_map<LangSharedString, std::unique_ptr<MisspellRangesVec>, LangSharedString::Hash> SharedStringMapType;
|
||||
#endif
|
||||
|
||||
SharedStringMapType maStringMisspells;
|
||||
CellMapType maEditTextMisspells;
|
||||
|
||||
virtual void dropCaches() override
|
||||
virtual OUString getCacheName() const override
|
||||
{
|
||||
return "SpellCheckCache";
|
||||
}
|
||||
|
||||
virtual bool dropCaches() override
|
||||
{
|
||||
clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void dumpState(rtl::OStringBuffer& rState) override
|
||||
@ -108,6 +119,10 @@ class SpellCheckContext::SpellCheckCache : public CacheOwner
|
||||
public:
|
||||
|
||||
SpellCheckCache()
|
||||
#if defined __cpp_lib_memory_resource
|
||||
: maStringMisspells(&CacheOwner::GetMemoryResource())
|
||||
, maEditTextMisspells(&CacheOwner::GetMemoryResource())
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
@ -153,8 +168,8 @@ public:
|
||||
|
||||
void clear()
|
||||
{
|
||||
maStringMisspells.clear();
|
||||
maEditTextMisspells.clear();
|
||||
SharedStringMapType(maStringMisspells.get_allocator()).swap(maStringMisspells);
|
||||
CellMapType(maEditTextMisspells.get_allocator()).swap(maEditTextMisspells);
|
||||
}
|
||||
|
||||
void clearEditTextMap()
|
||||
|
@ -58,7 +58,7 @@
|
||||
#include <svx/unopage.hxx>
|
||||
#include <comphelper/threadpool.hxx>
|
||||
#include <atomic>
|
||||
#include <deque>
|
||||
#include <vector>
|
||||
#include <libxml/xmlwriter.h>
|
||||
#include <osl/diagnose.h>
|
||||
#include <flyfrm.hxx>
|
||||
@ -74,7 +74,12 @@ class SwOLELRUCache
|
||||
, public CacheOwner
|
||||
{
|
||||
private:
|
||||
std::deque<SwOLEObj *> m_OleObjects;
|
||||
#if defined __cpp_lib_memory_resource
|
||||
typedef std::pmr::vector<SwOLEObj*> vector_t;
|
||||
#else
|
||||
typedef std::vector<SwOLEObj*> vector_t;
|
||||
#endif
|
||||
vector_t m_OleObjects;
|
||||
sal_Int32 m_nLRU_InitSize;
|
||||
static uno::Sequence< OUString > GetPropertyNames();
|
||||
|
||||
@ -82,9 +87,15 @@ private:
|
||||
|
||||
void tryShrinkCacheTo(sal_Int32 nVal);
|
||||
|
||||
virtual void dropCaches() override
|
||||
virtual OUString getCacheName() const override
|
||||
{
|
||||
return "SwOLELRUCache";
|
||||
}
|
||||
|
||||
virtual bool dropCaches() override
|
||||
{
|
||||
tryShrinkCacheTo(0);
|
||||
return m_OleObjects.empty();
|
||||
}
|
||||
|
||||
virtual void dumpState(rtl::OStringBuffer& rState) override
|
||||
@ -1299,6 +1310,9 @@ void SwOLEObj::dumpAsXml(xmlTextWriterPtr pWriter) const
|
||||
|
||||
SwOLELRUCache::SwOLELRUCache()
|
||||
: utl::ConfigItem(u"Office.Common/Cache"_ustr)
|
||||
#if defined __cpp_lib_memory_resource
|
||||
, m_OleObjects(&GetMemoryResource())
|
||||
#endif
|
||||
, m_nLRU_InitSize( 20 )
|
||||
{
|
||||
EnableNotification( GetPropertyNames() );
|
||||
@ -1378,7 +1392,7 @@ void SwOLELRUCache::InsertObj( SwOLEObj& rObj )
|
||||
if ( pObj->UnloadObject() )
|
||||
nCount--;
|
||||
}
|
||||
m_OleObjects.push_front(&rObj);
|
||||
m_OleObjects.insert(m_OleObjects.begin(), &rObj);
|
||||
}
|
||||
|
||||
void SwOLELRUCache::RemoveObj( SwOLEObj& rObj )
|
||||
|
@ -467,6 +467,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
|
||||
vcl/source/app/sound \
|
||||
vcl/source/app/stdtext \
|
||||
vcl/source/app/svapp \
|
||||
vcl/source/app/svcache \
|
||||
vcl/source/app/svdata \
|
||||
vcl/source/app/svmain \
|
||||
vcl/source/app/timer \
|
||||
|
@ -24,9 +24,11 @@
|
||||
#include <o3tl/hash_combine.hxx>
|
||||
|
||||
#include <vcl/dllapi.h>
|
||||
#include <vcl/dropcache.hxx>
|
||||
|
||||
#include <unicode/uscript.h>
|
||||
|
||||
#include <new>
|
||||
#include <vector>
|
||||
|
||||
namespace vcl::text
|
||||
@ -47,7 +49,11 @@ struct Run
|
||||
class VCL_DLLPUBLIC TextLayoutCache
|
||||
{
|
||||
public:
|
||||
#if defined __cpp_lib_memory_resource
|
||||
std::pmr::vector<vcl::text::Run> runs;
|
||||
#else
|
||||
std::vector<vcl::text::Run> runs;
|
||||
#endif
|
||||
TextLayoutCache(sal_Unicode const* pStr, sal_Int32 const nEnd);
|
||||
// Creates a cached instance.
|
||||
static std::shared_ptr<const vcl::text::TextLayoutCache> Create(OUString const&);
|
||||
|
@ -56,7 +56,8 @@ public:
|
||||
void checkStartReduceTimer();
|
||||
void reduceMemory(std::unique_lock<std::mutex>& rGuard, bool bDropAll = false);
|
||||
void loopAndReduceMemory(std::unique_lock<std::mutex>& rGuard, bool bDropAll = false);
|
||||
virtual void dropCaches() override;
|
||||
virtual OUString getCacheName() const override;
|
||||
virtual bool dropCaches() override;
|
||||
virtual void dumpState(rtl::OStringBuffer& rState) override;
|
||||
};
|
||||
|
||||
|
52
vcl/inc/svcache.hxx
Normal file
52
vcl/inc/svcache.hxx
Normal file
@ -0,0 +1,52 @@
|
||||
/* -*- 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 <rtl/alloc.h>
|
||||
#include <o3tl/numeric.hxx>
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <version>
|
||||
#if defined __cpp_lib_memory_resource
|
||||
#include <memory_resource>
|
||||
#endif
|
||||
|
||||
#if defined __cpp_lib_memory_resource
|
||||
|
||||
constexpr unsigned int nAlignments = o3tl::number_of_bits(alignof(std::max_align_t));
|
||||
|
||||
class CacheMemory : public std::pmr::memory_resource
|
||||
{
|
||||
public:
|
||||
CacheMemory();
|
||||
~CacheMemory();
|
||||
|
||||
static CacheMemory& GetMemoryResource();
|
||||
|
||||
size_t GetAllocatedPages() const;
|
||||
|
||||
private:
|
||||
std::array<rtl_arena_type*, nAlignments> maCacheArenas;
|
||||
size_t mnSmallest;
|
||||
size_t mnLargest;
|
||||
size_t mnPageSize;
|
||||
size_t mnAllocatedPages;
|
||||
size_t mnMaxAllocatedPages;
|
||||
|
||||
static void* allocPages(rtl_arena_type* arena, sal_Size* size);
|
||||
static void freePages(rtl_arena_type* arena, void* address, sal_Size size);
|
||||
|
||||
virtual void* do_allocate(std::size_t bytes, std::size_t alignment) override;
|
||||
virtual void do_deallocate(void* p, std::size_t bytes, std::size_t alignment) override;
|
||||
virtual bool do_is_equal(const std::pmr::memory_resource& other) const noexcept override;
|
||||
};
|
||||
#endif
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
|
174
vcl/source/app/svcache.cxx
Normal file
174
vcl/source/app/svcache.cxx
Normal file
@ -0,0 +1,174 @@
|
||||
/* -*- 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/.
|
||||
*
|
||||
* This file incorporates work covered by the following license notice:
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed
|
||||
* with this work for additional information regarding copyright
|
||||
* ownership. The ASF licenses this file to you under the Apache
|
||||
* License, Version 2.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
||||
*/
|
||||
|
||||
#include <vcl/dropcache.hxx>
|
||||
#include <svcache.hxx>
|
||||
#include <svdata.hxx>
|
||||
#if defined SAL_UNX
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/mman.h>
|
||||
#elif defined _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#else
|
||||
#error Unsupported platform
|
||||
#endif
|
||||
|
||||
CacheOwner::CacheOwner()
|
||||
{
|
||||
if (ImplSVData* pSVData = ImplGetSVData())
|
||||
{
|
||||
pSVData->registerCacheOwner(*this);
|
||||
return;
|
||||
}
|
||||
SAL_WARN("vcl.app", "Cache owner ctor before ImplSVData created. This is useless.");
|
||||
}
|
||||
|
||||
CacheOwner::~CacheOwner()
|
||||
{
|
||||
if (ImplSVData* pSVData = ImplGetSVData())
|
||||
pSVData->deregisterCacheOwner(*this);
|
||||
}
|
||||
|
||||
#if defined __cpp_lib_memory_resource
|
||||
|
||||
#define MEMORY_ALIGN(value, align) (((value) + ((align)-1)) & ~((align)-1))
|
||||
|
||||
void* CacheMemory::allocPages(rtl_arena_type* arena, sal_Size* size)
|
||||
{
|
||||
CacheMemory* pCacheMemory = reinterpret_cast<CacheMemory*>(arena);
|
||||
|
||||
std::size_t n = MEMORY_ALIGN(*size, pCacheMemory->mnPageSize);
|
||||
void* p;
|
||||
#if defined SAL_UNX
|
||||
p = mmap(nullptr, n, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
if (p == MAP_FAILED)
|
||||
p = nullptr;
|
||||
#elif defined _WIN32
|
||||
p = VirtualAlloc(nullptr, n, MEM_COMMIT, PAGE_READWRITE);
|
||||
#endif
|
||||
if (p != nullptr)
|
||||
{
|
||||
pCacheMemory->mnAllocatedPages += (n / pCacheMemory->mnPageSize);
|
||||
pCacheMemory->mnMaxAllocatedPages
|
||||
= std::max(pCacheMemory->mnMaxAllocatedPages, pCacheMemory->mnAllocatedPages);
|
||||
*size = n;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void CacheMemory::freePages(rtl_arena_type* arena, void* address, sal_Size size)
|
||||
{
|
||||
CacheMemory* pCacheMemory = reinterpret_cast<CacheMemory*>(arena);
|
||||
#if defined SAL_UNX
|
||||
munmap(address, size);
|
||||
#elif defined _WIN32
|
||||
(void)size; // unused
|
||||
VirtualFree(address, 0, MEM_RELEASE);
|
||||
#endif
|
||||
pCacheMemory->mnAllocatedPages -= (size / pCacheMemory->mnPageSize);
|
||||
}
|
||||
|
||||
CacheMemory::CacheMemory()
|
||||
: maCacheArenas{ nullptr }
|
||||
, mnSmallest(SAL_MAX_SIZE)
|
||||
, mnLargest(0)
|
||||
, mnAllocatedPages(0)
|
||||
, mnMaxAllocatedPages(0)
|
||||
{
|
||||
#if defined SAL_UNX
|
||||
#if defined FREEBSD || defined NETBSD || defined OPENBSD || defined DRAGONFLY || defined HAIKU
|
||||
mnPageSize = getpagesize();
|
||||
#else
|
||||
// coverity[ tainted_data_return : FALSE ] version 2023.12.2
|
||||
mnPageSize = sysconf(_SC_PAGESIZE);
|
||||
#endif
|
||||
#elif defined _WIN32
|
||||
SYSTEM_INFO info;
|
||||
GetSystemInfo(&info);
|
||||
mnPageSize = info.dwPageSize;
|
||||
#else
|
||||
#error Unsupported platform
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t CacheMemory::GetAllocatedPages() const { return mnAllocatedPages; }
|
||||
|
||||
CacheMemory::~CacheMemory()
|
||||
{
|
||||
SAL_INFO("vcl", "cachememory, smallest/largest are: "
|
||||
<< mnSmallest << ", " << mnLargest << "total pages allocated: "
|
||||
<< mnMaxAllocatedPages << ", current allocated pages" << mnAllocatedPages);
|
||||
for (size_t i = 0; i < maCacheArenas.size(); ++i)
|
||||
{
|
||||
if (!maCacheArenas[i])
|
||||
continue;
|
||||
SAL_INFO("vcl", "cachememory, destroying arena for alignment: " << (1 << i));
|
||||
rtl_arena_destroy(maCacheArenas[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void* CacheMemory::do_allocate(std::size_t bytes, std::size_t alignment)
|
||||
{
|
||||
alignment = std::max<std::size_t>(alignment, 4);
|
||||
const unsigned int nSlot = o3tl::number_of_bits(alignment) - 1;
|
||||
if (!maCacheArenas[nSlot])
|
||||
{
|
||||
maCacheArenas[nSlot]
|
||||
= rtl_arena_create("cache_internal_arena", alignment, 0,
|
||||
reinterpret_cast<rtl_arena_type*>(this), allocPages, freePages, 0);
|
||||
}
|
||||
|
||||
mnSmallest = std::min(mnSmallest, bytes);
|
||||
mnLargest = std::max(mnLargest, bytes);
|
||||
sal_Size size = MEMORY_ALIGN(bytes, alignment);
|
||||
return rtl_arena_alloc(maCacheArenas[nSlot], &size);
|
||||
}
|
||||
|
||||
void CacheMemory::do_deallocate(void* p, std::size_t bytes, std::size_t alignment)
|
||||
{
|
||||
alignment = std::max<std::size_t>(alignment, 4);
|
||||
const unsigned int nSlot = o3tl::number_of_bits(alignment) - 1;
|
||||
sal_Size size = MEMORY_ALIGN(bytes, alignment);
|
||||
rtl_arena_free(maCacheArenas[nSlot], p, size);
|
||||
}
|
||||
|
||||
bool CacheMemory::do_is_equal(const std::pmr::memory_resource& other) const noexcept
|
||||
{
|
||||
SAL_WARN("vcl", "CacheMemory::do_is_equal called");
|
||||
return &other == this;
|
||||
}
|
||||
|
||||
//static
|
||||
CacheMemory& CacheMemory::GetMemoryResource()
|
||||
{
|
||||
static CacheMemory aCacheMemory;
|
||||
return aCacheMemory;
|
||||
}
|
||||
|
||||
//static
|
||||
std::pmr::memory_resource& CacheOwner::GetMemoryResource()
|
||||
{
|
||||
return CacheMemory::GetMemoryResource();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
|
@ -45,6 +45,7 @@
|
||||
#include <vcl/toolkit/dialog.hxx>
|
||||
#include <salinst.hxx>
|
||||
#include <salgdi.hxx>
|
||||
#include <svcache.hxx>
|
||||
#include <svdata.hxx>
|
||||
#include <salsys.hxx>
|
||||
#include <windowdev.hxx>
|
||||
@ -444,24 +445,18 @@ void ImplSVData::dropCaches()
|
||||
|
||||
// copy, some caches self-delete on emptying, e.g. SwOLELRUCache
|
||||
auto aCacheOwners = maCacheOwners;
|
||||
bool bAllCachesDropped = true;
|
||||
for (CacheOwner* pCacheOwner : aCacheOwners)
|
||||
pCacheOwner->dropCaches();
|
||||
}
|
||||
|
||||
CacheOwner::CacheOwner()
|
||||
{
|
||||
if (ImplSVData* pSVData = ImplGetSVData())
|
||||
{
|
||||
pSVData->registerCacheOwner(*this);
|
||||
return;
|
||||
bool bCacheDropped = pCacheOwner->dropCaches();
|
||||
SAL_WARN_IF(!bCacheDropped, "vcl", "Cache " << pCacheOwner->getCacheName() << " drop failed");
|
||||
bAllCachesDropped &= bCacheDropped;
|
||||
}
|
||||
SAL_WARN("vcl.app", "Cache owner ctor before ImplSVData created. This is useless.");
|
||||
}
|
||||
|
||||
CacheOwner::~CacheOwner()
|
||||
{
|
||||
if (ImplSVData* pSVData = ImplGetSVData())
|
||||
pSVData->deregisterCacheOwner(*this);
|
||||
#if defined __cpp_lib_memory_resource
|
||||
assert(!bAllCachesDropped || CacheMemory::GetMemoryResource().GetAllocatedPages() == 0);
|
||||
#endif
|
||||
(void)bAllCachesDropped;
|
||||
}
|
||||
|
||||
void ImplSVData::dumpState(rtl::OStringBuffer &rState)
|
||||
|
@ -590,7 +590,13 @@ size_t SalLayoutGlyphsCache::GlyphsCost::operator()(const SalLayoutGlyphs& glyph
|
||||
return cost;
|
||||
}
|
||||
|
||||
void SalLayoutGlyphsCache::dropCaches() { clear(); }
|
||||
OUString SalLayoutGlyphsCache::getCacheName() const { return "SalLayoutGlyphsCache"; }
|
||||
|
||||
bool SalLayoutGlyphsCache::dropCaches()
|
||||
{
|
||||
clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
void SalLayoutGlyphsCache::dumpState(rtl::OStringBuffer& rState)
|
||||
{
|
||||
|
@ -119,10 +119,13 @@ void MemoryManager::swappedOut(MemoryManaged* pMemoryManaged, sal_Int64 nNewSize
|
||||
changeExisting(pMemoryManaged, nNewSize);
|
||||
}
|
||||
|
||||
void MemoryManager::dropCaches()
|
||||
OUString MemoryManager::getCacheName() const { return "MemoryManager"; }
|
||||
|
||||
bool MemoryManager::dropCaches()
|
||||
{
|
||||
std::unique_lock aGuard(maMutex);
|
||||
reduceMemory(aGuard, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
void MemoryManager::dumpState(rtl::OStringBuffer& rState)
|
||||
|
@ -43,7 +43,14 @@
|
||||
namespace {
|
||||
struct WavyLineCache final : public CacheOwner
|
||||
{
|
||||
WavyLineCache () : m_aItems( 10 ) {}
|
||||
WavyLineCache()
|
||||
#if defined __cpp_lib_memory_resource
|
||||
: m_aItems(10, &GetMemoryResource())
|
||||
#else
|
||||
: m_aItems(10)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
bool find( Color aLineColor, size_t nLineWidth, size_t nWaveHeight, size_t nWordWidth, BitmapEx& rOutput )
|
||||
{
|
||||
@ -67,9 +74,12 @@ namespace {
|
||||
rOutput = aBitmap;
|
||||
}
|
||||
|
||||
virtual void dropCaches() override
|
||||
virtual OUString getCacheName() const override { return "WavyLineCache"; }
|
||||
|
||||
virtual bool dropCaches() override
|
||||
{
|
||||
m_aItems.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void dumpState(rtl::OStringBuffer& rState) override
|
||||
|
@ -29,9 +29,14 @@
|
||||
#include <officecfg/Office/Common.hxx>
|
||||
#include <vcl/dropcache.hxx>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace vcl::text
|
||||
{
|
||||
TextLayoutCache::TextLayoutCache(sal_Unicode const* pStr, sal_Int32 const nEnd)
|
||||
#if defined __cpp_lib_memory_resource
|
||||
: runs(&CacheOwner::GetMemoryResource())
|
||||
#endif
|
||||
{
|
||||
vcl::ScriptRun aScriptRun(reinterpret_cast<const UChar*>(pStr), nEnd);
|
||||
while (aScriptRun.next())
|
||||
@ -57,10 +62,18 @@ struct TextLayoutCacheMap : public CacheOwner
|
||||
FastStringCompareEqual, TextLayoutCacheCost>
|
||||
Cache;
|
||||
|
||||
#if defined __cpp_lib_memory_resource
|
||||
std::pmr::polymorphic_allocator<TextLayoutCache> allocator;
|
||||
#endif
|
||||
Cache cache;
|
||||
|
||||
TextLayoutCacheMap(int capacity)
|
||||
#if defined __cpp_lib_memory_resource
|
||||
: allocator(&CacheOwner::GetMemoryResource())
|
||||
, cache(capacity, &CacheOwner::GetMemoryResource())
|
||||
#else
|
||||
: cache(capacity)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
@ -69,12 +82,23 @@ struct TextLayoutCacheMap : public CacheOwner
|
||||
auto it = cache.find(rString);
|
||||
if (it != cache.end())
|
||||
return it->second;
|
||||
auto ret = std::make_shared<const TextLayoutCache>(rString.getStr(), rString.getLength());
|
||||
#if defined __cpp_lib_memory_resource
|
||||
auto ret = std::allocate_shared<TextLayoutCache>(allocator, rString.getStr(),
|
||||
rString.getLength());
|
||||
#else
|
||||
auto ret = std::make_shared<TextLayoutCache>(rString.getStr(), rString.getLength());
|
||||
#endif
|
||||
cache.insert({ rString, ret });
|
||||
return ret;
|
||||
}
|
||||
|
||||
virtual void dropCaches() override { cache.clear(); }
|
||||
virtual OUString getCacheName() const override { return "TextLayoutCache"; }
|
||||
|
||||
virtual bool dropCaches() override
|
||||
{
|
||||
cache.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void dumpState(rtl::OStringBuffer& rState) override
|
||||
{
|
||||
@ -100,7 +124,7 @@ std::shared_ptr<const TextLayoutCache> TextLayoutCache::Create(OUString const& r
|
||||
: 100);
|
||||
if (TextLayoutCacheMap* map = cache.get())
|
||||
return map->Create(rString);
|
||||
return std::make_shared<const TextLayoutCache>(rString.getStr(), rString.getLength());
|
||||
return std::make_shared<TextLayoutCache>(rString.getStr(), rString.getLength());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,7 +121,12 @@ private:
|
||||
|
||||
public:
|
||||
CachedFontConfigFontOptions()
|
||||
: lru_options_cache(10) // arbitrary cache size of 10
|
||||
// arbitrary cache size of 10
|
||||
#if defined __cpp_lib_memory_resource
|
||||
: lru_options_cache(10, &CacheOwner::GetMemoryResource())
|
||||
#else
|
||||
: lru_options_cache(10)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
@ -139,9 +144,15 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
virtual void dropCaches() override
|
||||
virtual OUString getCacheName() const override
|
||||
{
|
||||
return "CachedFontConfigFontOptions";
|
||||
}
|
||||
|
||||
virtual bool dropCaches() override
|
||||
{
|
||||
lru_options_cache.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void dumpState(rtl::OStringBuffer& rState) override
|
||||
|
@ -62,12 +62,22 @@ public:
|
||||
};
|
||||
|
||||
private:
|
||||
typedef std::deque< std::pair<cairo_font_face_t*, CacheId> > LRUFonts;
|
||||
#if defined __cpp_lib_memory_resource
|
||||
typedef std::pmr::vector< std::pair<cairo_font_face_t*, CacheId> > LRUFonts;
|
||||
#else
|
||||
typedef std::vector< std::pair<cairo_font_face_t*, CacheId> > LRUFonts;
|
||||
#endif
|
||||
LRUFonts maLRUFonts;
|
||||
|
||||
virtual void dropCaches() override
|
||||
virtual OUString getCacheName() const override
|
||||
{
|
||||
maLRUFonts.clear();
|
||||
return "CairoFontsCache";
|
||||
}
|
||||
|
||||
virtual bool dropCaches() override
|
||||
{
|
||||
LRUFonts(maLRUFonts.get_allocator()).swap(maLRUFonts);
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void dumpState(rtl::OStringBuffer& rState) override
|
||||
@ -77,6 +87,15 @@ private:
|
||||
}
|
||||
|
||||
public:
|
||||
CairoFontsCache()
|
||||
#if defined __cpp_lib_memory_resource
|
||||
: maLRUFonts(&CacheOwner::GetMemoryResource())
|
||||
#else
|
||||
: maLRUFonts()
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
void CacheFont(cairo_font_face_t* pFont, const CacheId &rId);
|
||||
cairo_font_face_t* FindCachedFont(const CacheId &rId);
|
||||
};
|
||||
@ -89,19 +108,19 @@ CairoFontsCache& getCairoFontsCache()
|
||||
|
||||
void CairoFontsCache::CacheFont(cairo_font_face_t* pFont, const CairoFontsCache::CacheId &rId)
|
||||
{
|
||||
maLRUFonts.push_front( std::pair<cairo_font_face_t*, CairoFontsCache::CacheId>(pFont, rId) );
|
||||
maLRUFonts.push_back( std::pair<cairo_font_face_t*, CairoFontsCache::CacheId>(pFont, rId) );
|
||||
if (maLRUFonts.size() > 8)
|
||||
{
|
||||
cairo_font_face_destroy(maLRUFonts.back().first);
|
||||
maLRUFonts.pop_back();
|
||||
cairo_font_face_destroy(maLRUFonts.front().first);
|
||||
maLRUFonts.erase(maLRUFonts.begin());
|
||||
}
|
||||
}
|
||||
|
||||
cairo_font_face_t* CairoFontsCache::FindCachedFont(const CairoFontsCache::CacheId &rId)
|
||||
{
|
||||
auto aI = std::find_if(maLRUFonts.begin(), maLRUFonts.end(),
|
||||
auto aI = std::find_if(maLRUFonts.rbegin(), maLRUFonts.rend(),
|
||||
[&rId](const LRUFonts::value_type& rFont) { return rFont.second == rId; });
|
||||
if (aI != maLRUFonts.end())
|
||||
if (aI != maLRUFonts.rend())
|
||||
return aI->first;
|
||||
return nullptr;
|
||||
}
|
||||
|
Reference in New Issue
Block a user