27#if defined(SK_USE_DISCARDABLE_SCALEDIMAGECACHE)
47#ifndef SK_DISCARDABLEMEMORY_SCALEDIMAGECACHE_COUNT_LIMIT
48# define SK_DISCARDABLEMEMORY_SCALEDIMAGECACHE_COUNT_LIMIT 1024
51#ifndef SK_DEFAULT_IMAGE_CACHE_LIMIT
52 #define SK_DEFAULT_IMAGE_CACHE_LIMIT (32 * 1024 * 1024)
59 static const int kUnhashedLocal32s = 2;
60 static const int kSharedIDLocal32s = 2;
61 static const int kHashedLocal32s = kSharedIDLocal32s + (
sizeof(fNamespace) >> 2);
62 static const int kLocal32s = kUnhashedLocal32s + kHashedLocal32s;
64 static_assert(
sizeof(
Key) == (kLocal32s << 2),
"unaccounted_key_locals");
65 static_assert(
sizeof(
Key) == offsetof(
Key, fNamespace) +
sizeof(fNamespace),
66 "namespace_field_must_be_last");
68 fCount32 =
SkToS32(kLocal32s + (dataSize >> 2));
69 fSharedID_lo = (uint32_t)(sharedID & 0xFFFFFFFF);
70 fSharedID_hi = (uint32_t)(sharedID >> 32);
71 fNamespace = nameSpace;
74 (fCount32 - kUnhashedLocal32s) << 2);
87 public THashTable<SkResourceCache::Rec*, SkResourceCache::Key, HashTraits> {};
92void SkResourceCache::init() {
98 fSingleAllocationByteLimit = 0;
102 fDiscardableFactory =
nullptr;
108 fDiscardableFactory = factory;
114 fTotalByteLimit = byteLimit;
130 this->checkMessages();
132 if (
auto found = fHash->
find(
key)) {
134 if (visitor(*rec, context)) {
135 this->moveToHead(rec);
146 const char suffix[] = {
'b',
'k',
'm',
'g',
't', 0 };
158 this->checkMessages();
164 if (
prev->canBePurged()) {
169 prev->postAddInstall(payload);
175 this->addToHead(rec);
183 SkDebugf(
"RC: add %5s %12p key %08x -- total %5s, count %d\n",
188 this->purgeAsNeeded();
191void SkResourceCache::remove(
Rec* rec) {
193 size_t used = rec->bytesUsed();
197 fHash->
remove(rec->getKey());
199 fTotalBytesUsed -= used;
208 SkDebugf(
"RC: remove %5s %12p key %08x -- total %5s, count %d\n",
209 bytesStr.
c_str(), rec, rec->getHash(), totalStr.
c_str(), fCount);
215void SkResourceCache::purgeAsNeeded(
bool forcePurge) {
219 if (fDiscardableFactory) {
221 byteLimit = UINT32_MAX;
224 byteLimit = fTotalByteLimit;
229 if (!forcePurge && fTotalBytesUsed < byteLimit && fCount < countLimit) {
234 if (rec->canBePurged()) {
243#ifdef SK_TRACK_PURGE_SHAREDID_HITRATE
244static int gPurgeCallCounter;
245static int gPurgeHitCounter;
253#ifdef SK_TRACK_PURGE_SHAREDID_HITRATE
254 gPurgeCallCounter += 1;
268#ifdef SK_TRACK_PURGE_SHAREDID_HITRATE
275#ifdef SK_TRACK_PURGE_SHAREDID_HITRATE
277 gPurgeHitCounter += 1;
280 SkDebugf(
"PurgeShared calls=%d hits=%d rate=%g\n", gPurgeCallCounter, gPurgeHitCounter,
281 gPurgeHitCounter * 100.0 / gPurgeCallCounter);
290 visitor(*rec, context);
298 size_t prevLimit = fTotalByteLimit;
299 fTotalByteLimit = newLimit;
300 if (newLimit < prevLimit) {
301 this->purgeAsNeeded();
307 this->checkMessages();
309 if (fDiscardableFactory) {
319void SkResourceCache::release(
Rec* rec) {
336 rec->fNext = rec->fPrev =
nullptr;
339void SkResourceCache::moveToHead(
Rec* rec) {
358void SkResourceCache::addToHead(
Rec* rec) {
361 rec->fPrev =
nullptr;
370 fTotalBytesUsed += rec->bytesUsed();
379void SkResourceCache::validate()
const {
380 if (
nullptr == fHead) {
386 if (fHead == fTail) {
400 const Rec* rec = fHead;
403 used += rec->bytesUsed();
414 used -= rec->bytesUsed();
426 SkDebugf(
"SkResourceCache: count=%d bytes=%zu %s\n",
427 fCount, fTotalBytesUsed, fDiscardableFactory ?
"discardable" :
"malloc");
431 size_t oldLimit = fSingleAllocationByteLimit;
432 fSingleAllocationByteLimit = newLimit;
437 return fSingleAllocationByteLimit;
442 size_t limit = fSingleAllocationByteLimit;
446 if (
nullptr == fDiscardableFactory) {
448 limit = fTotalByteLimit;
450 limit =
std::min(limit, fTotalByteLimit);
456void SkResourceCache::checkMessages() {
458 fPurgeSharedIDInbox.poll(&msgs);
459 for (
int i = 0;
i < msgs.
size(); ++
i) {
468 static SkMutex& mutex = *(
new SkMutex);
477#ifdef SK_USE_DISCARDABLE_SCALEDIMAGECACHE
585 SkImageFilter_Base::PurgeCache();
592 SkDebugf(
"RC: %12s bytes %9zu discardable %p\n",
605 dump->setDiscardableMemoryBacking(dumpName.
c_str(), *discardable);
609 dump->dumpNumericValue(dumpName.
c_str(),
"discardable_size",
"bytes", rec.
bytesUsed());
612 dump->setMemoryBacking(dumpName.
c_str(),
"malloc",
nullptr);
static float next(float f)
static float prev(float f)
static constexpr T SkAlign4(T x)
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static void * sk_malloc_throw(size_t size)
static constexpr int32_t SK_MaxS32
#define DECLARE_SKMESSAGEBUS_MESSAGE(Message, IDType, AllowCopyableMessage)
static void make_size_str(size_t size, SkString *str)
static SkMutex & resource_cache_mutex()
static void dump_visitor(const SkResourceCache::Rec &rec, void *)
static SkResourceCache * get_cache()
static bool SkShouldPostMessageToBus(const SkResourceCache::PurgeSharedIDMessage &, uint32_t)
static void sk_trace_dump_visitor(const SkResourceCache::Rec &rec, void *context)
static SkResourceCache * gResourceCache
#define SK_DISCARDABLEMEMORY_SCALEDIMAGECACHE_COUNT_LIMIT
static bool gDumpCacheTransactions
#define SK_DEFAULT_IMAGE_CACHE_LIMIT
SK_API SkString SkStringPrintf(const char *format,...) SK_PRINTF_LIKE(1
Creates a new string and writes into it using a printf()-style format.
constexpr int32_t SkToS32(S x)
static constexpr uint32_t SK_InvalidUniqueID
static void dump(const float m[20], SkYUVColorSpace cs, bool rgb2yuv)
static SkDiscardableMemory * Create(size_t bytes)
static size_t GetResourceCacheTotalByteLimit()
static size_t GetResourceCacheSingleAllocationByteLimit()
static size_t SetResourceCacheSingleAllocationByteLimit(size_t newLimit)
static size_t SetResourceCacheTotalByteLimit(size_t newLimit)
static void PurgeResourceCache()
static size_t GetResourceCacheTotalBytesUsed()
static void Post(Message m)
SkResourceCache(DiscardableFactory)
static size_t SetSingleAllocationByteLimit(size_t)
static SkCachedData * NewCachedData(size_t bytes)
static void Add(Rec *, void *payload=nullptr)
size_t getSingleAllocationByteLimit() const
size_t getTotalByteLimit() const
static size_t GetEffectiveSingleAllocationByteLimit()
DiscardableFactory discardableFactory() const
size_t getTotalBytesUsed() const
void visitAll(Visitor, void *context)
static void PostPurgeSharedID(uint64_t sharedID)
static size_t GetTotalBytesUsed()
void purgeSharedID(uint64_t sharedID)
static void CheckMessages()
static DiscardableFactory GetDiscardableFactory()
bool find(const Key &, FindVisitor, void *context)
static void DumpMemoryStatistics(SkTraceMemoryDump *dump)
static size_t GetSingleAllocationByteLimit()
static void VisitAll(Visitor, void *context)
static size_t GetTotalByteLimit()
static bool Find(const Key &key, FindVisitor, void *context)
static void TestDumpMemoryStatistics()
size_t setTotalByteLimit(size_t newLimit)
SkCachedData * newCachedData(size_t bytes)
SkDiscardableMemory *(* DiscardableFactory)(size_t bytes)
size_t setSingleAllocationByteLimit(size_t maximumAllocationSize)
size_t getEffectiveSingleAllocationByteLimit() const
static size_t SetTotalByteLimit(size_t newLimit)
void add(Rec *, void *payload=nullptr)
void printf(const char format[],...) SK_PRINTF_LIKE(2
const char * c_str() const
void remove(const K &key)
T * find(const K &key) const
static float min(float r, float g, float b)
uint32_t Hash32(const void *data, size_t bytes, uint32_t seed)
Visitor(Ts...) -> Visitor< Ts... >
static uint32_t Hash(uint32_t key)
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
uint64_t getSharedID() const
void init(void *nameSpace, uint64_t sharedID, size_t dataSize)
virtual void postAddInstall(void *)
virtual const char * getCategory() const =0
virtual SkDiscardableMemory * diagnostic_only_getDiscardable() const
virtual size_t bytesUsed() const =0
virtual const Key & getKey() const =0
virtual bool canBePurged()