Skip to content
Permalink
Browse files
Add notifyutil callbacks to dump the memory cache, and the list of li…
…ve Pages and Documents

https://bugs.webkit.org/show_bug.cgi?id=185853

Reviewed by Keith Miller.
Source/WebCore:

Add a notifyutil callback to dump the PageCache, which dumps the stats, and the list of live pages.
This can be invoked on iOS and macOS via "notifyutil -p com.apple.WebKit.showPageCache".

Add a notifyutil callback that dumps the list of all Pages, and the list of all Documents, with
Document pointer address and URL.
This can be invoked on iOS and macOS via "notifyutil -p com.apple.WebKit.showAllDocuments".

* history/PageCache.cpp:
(WebCore::PageCache::PageCache):
(WebCore::PageCache::dump const):
* history/PageCache.h:
* loader/cache/CachedResource.h:
(WebCore::CachedResource::numberOfClients const):
(WebCore::CachedResource::count const): Deleted.
* loader/cache/MemoryCache.cpp:
(WebCore::MemoryCache::MemoryCache):
(WebCore::MemoryCache::pruneLiveResourcesToSize):
(WebCore::MemoryCache::dumpStats):
(WebCore::MemoryCache::dumpLRULists const):
* loader/cache/MemoryCache.h:
* page/mac/PageMac.mm:
(WebCore::Page::platformInitialize):

Source/WebCore/PAL:

Compile registerNotifyCallback in release builds.

* pal/Logging.cpp:
(PAL::registerNotifyCallback):
* pal/Logging.h:


Canonical link: https://commits.webkit.org/201345@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232098 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
smfr committed May 23, 2018
1 parent d2632b8 commit 97fb95ea32f12ad0e2d55cb964674991abf7a8dc
@@ -1,3 +1,33 @@
2018-05-22 Simon Fraser <simon.fraser@apple.com>

Add notifyutil callbacks to dump the memory cache, and the list of live Pages and Documents
https://bugs.webkit.org/show_bug.cgi?id=185853

Reviewed by Keith Miller.

Add a notifyutil callback to dump the PageCache, which dumps the stats, and the list of live pages.
This can be invoked on iOS and macOS via "notifyutil -p com.apple.WebKit.showPageCache".

Add a notifyutil callback that dumps the list of all Pages, and the list of all Documents, with
Document pointer address and URL.
This can be invoked on iOS and macOS via "notifyutil -p com.apple.WebKit.showAllDocuments".

* history/PageCache.cpp:
(WebCore::PageCache::PageCache):
(WebCore::PageCache::dump const):
* history/PageCache.h:
* loader/cache/CachedResource.h:
(WebCore::CachedResource::numberOfClients const):
(WebCore::CachedResource::count const): Deleted.
* loader/cache/MemoryCache.cpp:
(WebCore::MemoryCache::MemoryCache):
(WebCore::MemoryCache::pruneLiveResourcesToSize):
(WebCore::MemoryCache::dumpStats):
(WebCore::MemoryCache::dumpLRULists const):
* loader/cache/MemoryCache.h:
* page/mac/PageMac.mm:
(WebCore::Page::platformInitialize):

2018-05-22 Dean Jackson <dino@apple.com>

Optimized path zoom animation needs a valid UIImage and CGRect
@@ -1,3 +1,16 @@
2018-05-22 Simon Fraser <simon.fraser@apple.com>

Add notifyutil callbacks to dump the memory cache, and the list of live Pages and Documents
https://bugs.webkit.org/show_bug.cgi?id=185853

Reviewed by Keith Miller.

Compile registerNotifyCallback in release builds.

* pal/Logging.cpp:
(PAL::registerNotifyCallback):
* pal/Logging.h:

2018-05-22 Ryan Haddad <ryanhaddad@apple.com>

Unreviewed, rolling out r232052.
@@ -81,7 +81,8 @@ void initializeLogChannelsIfNecessary(std::optional<String> logChannelString)
WTFInitializeLogChannelStatesFromString(logChannels, logChannelCount, enabledChannelsString.utf8().data());
}

#ifndef NDEBUG
#endif // !LOG_DISABLED || !RELEASE_LOG_DISABLED

void registerNotifyCallback(const String& notifyID, WTF::Function<void()>&& callback)
{
#if PLATFORM(COCOA)
@@ -94,9 +95,6 @@ void registerNotifyCallback(const String& notifyID, WTF::Function<void()>&& call
UNUSED_PARAM(callback);
#endif
}
#endif

#endif // !LOG_DISABLED || !RELEASE_LOG_DISABLED

} // namespace WebCore

@@ -45,11 +45,10 @@ PAL_LOG_CHANNELS(DECLARE_LOG_CHANNEL)
String logLevelString();
bool isLogChannelEnabled(const String& name);
PAL_EXPORT void setLogChannelToAccumulate(const String& name);
#ifndef NDEBUG
void registerNotifyCallback(const String& notifyID, WTF::Function<void()>&& callback);
#endif

#endif // !LOG_DISABLED || !RELEASE_LOG_DISABLED

PAL_EXPORT void registerNotifyCallback(const String&, WTF::Function<void()>&&);

} // namespace PAL

@@ -48,6 +48,7 @@
#include "ScriptDisallowedScope.h"
#include "Settings.h"
#include "SubframeLoader.h"
#include <pal/Logging.h>
#include <wtf/MemoryPressureHandler.h>
#include <wtf/NeverDestroyed.h>
#include <wtf/SetForScope.h>
@@ -277,7 +278,26 @@ PageCache& PageCache::singleton()
static NeverDestroyed<PageCache> globalPageCache;
return globalPageCache;
}


PageCache::PageCache()
{
static std::once_flag onceFlag;
std::call_once(onceFlag, [] {
PAL::registerNotifyCallback("com.apple.WebKit.showPageCache", [] {
PageCache::singleton().dump();
});
});
}

void PageCache::dump() const
{
WTFLogAlways("\nPage Cache:");
for (auto& item : m_items) {
CachedPage& cachedPage = *item->m_cachedPage;
WTFLogAlways(" Page %p, document %p %s", &cachedPage.page(), cachedPage.document(), cachedPage.document() ? cachedPage.document()->url().string().utf8().data() : "");
}
}

bool PageCache::canCache(Page& page) const
{
if (!m_maxSize) {
@@ -68,12 +68,13 @@ class PageCache {
#endif

private:
PageCache() = default; // Use singleton() instead.
PageCache();
~PageCache() = delete; // Make sure nobody accidentally calls delete -- WebCore does not delete singletons.

static bool canCachePageContainingThisFrame(Frame&);

void prune(PruningReason);
void dump() const;

ListHashSet<RefPtr<HistoryItem>> m_items;
unsigned m_maxSize {0};
@@ -144,7 +144,7 @@ class CachedResource {
virtual void allClientsRemoved();
void destroyDecodedDataIfNeeded();

unsigned count() const { return m_clients.size(); }
unsigned numberOfClients() const { return m_clients.size(); }

Status status() const { return static_cast<Status>(m_status); }
void setStatus(Status status) { m_status = status; }
@@ -39,6 +39,7 @@
#include "WorkerGlobalScope.h"
#include "WorkerLoaderProxy.h"
#include "WorkerThread.h"
#include <pal/Logging.h>
#include <stdio.h>
#include <wtf/MathExtras.h>
#include <wtf/NeverDestroyed.h>
@@ -59,16 +60,19 @@ MemoryCache& MemoryCache::singleton()
}

MemoryCache::MemoryCache()
: m_disabled(false)
, m_inPruneResources(false)
, m_capacity(cDefaultCacheCapacity)
, m_minDeadCapacity(0)
: m_capacity(cDefaultCacheCapacity)
, m_maxDeadCapacity(cDefaultCacheCapacity)
, m_liveSize(0)
, m_deadSize(0)
, m_pruneTimer(*this, &MemoryCache::prune)
{
static_assert(sizeof(long long) > sizeof(unsigned), "Numerical overflow can happen when adjusting the size of the cached memory.");

static std::once_flag onceFlag;
std::call_once(onceFlag, [] {
PAL::registerNotifyCallback("com.apple.WebKit.showMemoryCache", [] {
MemoryCache::singleton().dumpStats();
MemoryCache::singleton().dumpLRULists(true);
});
});
}

auto MemoryCache::sessionResourceMap(PAL::SessionID sessionID) const -> CachedResourceMap*
@@ -329,6 +333,7 @@ void MemoryCache::pruneLiveResourcesToSize(unsigned targetSize, bool shouldDestr

// Destroy our decoded data. This will remove us from m_liveDecodedResources, and possibly move us
// to a different LRU list in m_allResources.
WTFLogAlways("pruneLiveResourcesToSize: trying to prune %p", current);
current->destroyDecodedData();

if (targetSize && m_liveSize <= targetSize)
@@ -733,35 +738,47 @@ void MemoryCache::pruneSoon()
m_pruneTimer.startOneShot(0_s);
}

#ifndef NDEBUG
void MemoryCache::dumpStats()
{
Statistics s = getStatistics();
printf("%-13s %-13s %-13s %-13s %-13s\n", "", "Count", "Size", "LiveSize", "DecodedSize");
printf("%-13s %-13s %-13s %-13s %-13s\n", "-------------", "-------------", "-------------", "-------------", "-------------");
printf("%-13s %13d %13d %13d %13d\n", "Images", s.images.count, s.images.size, s.images.liveSize, s.images.decodedSize);
printf("%-13s %13d %13d %13d %13d\n", "CSS", s.cssStyleSheets.count, s.cssStyleSheets.size, s.cssStyleSheets.liveSize, s.cssStyleSheets.decodedSize);
WTFLogAlways("\nMemory Cache");
WTFLogAlways("%-13s %-13s %-13s %-13s %-13s\n", "", "Count", "Size", "LiveSize", "DecodedSize");
WTFLogAlways("%-13s %-13s %-13s %-13s %-13s\n", "-------------", "-------------", "-------------", "-------------", "-------------");
WTFLogAlways("%-13s %13d %13d %13d %13d\n", "Images", s.images.count, s.images.size, s.images.liveSize, s.images.decodedSize);
WTFLogAlways("%-13s %13d %13d %13d %13d\n", "CSS", s.cssStyleSheets.count, s.cssStyleSheets.size, s.cssStyleSheets.liveSize, s.cssStyleSheets.decodedSize);
#if ENABLE(XSLT)
printf("%-13s %13d %13d %13d %13d\n", "XSL", s.xslStyleSheets.count, s.xslStyleSheets.size, s.xslStyleSheets.liveSize, s.xslStyleSheets.decodedSize);
WTFLogAlways("%-13s %13d %13d %13d %13d\n", "XSL", s.xslStyleSheets.count, s.xslStyleSheets.size, s.xslStyleSheets.liveSize, s.xslStyleSheets.decodedSize);
#endif
printf("%-13s %13d %13d %13d %13d\n", "JavaScript", s.scripts.count, s.scripts.size, s.scripts.liveSize, s.scripts.decodedSize);
printf("%-13s %13d %13d %13d %13d\n", "Fonts", s.fonts.count, s.fonts.size, s.fonts.liveSize, s.fonts.decodedSize);
printf("%-13s %-13s %-13s %-13s %-13s\n\n", "-------------", "-------------", "-------------", "-------------", "-------------");
WTFLogAlways("%-13s %13d %13d %13d %13d\n", "JavaScript", s.scripts.count, s.scripts.size, s.scripts.liveSize, s.scripts.decodedSize);
WTFLogAlways("%-13s %13d %13d %13d %13d\n", "Fonts", s.fonts.count, s.fonts.size, s.fonts.liveSize, s.fonts.decodedSize);
WTFLogAlways("%-13s %-13s %-13s %-13s %-13s\n\n", "-------------", "-------------", "-------------", "-------------", "-------------");

unsigned countTotal = s.images.count + s.cssStyleSheets.count + s.scripts.count + s.fonts.count;
unsigned sizeTotal = s.images.size + s.cssStyleSheets.size + s.scripts.size + s.fonts.size;
unsigned liveSizeTotal = s.images.liveSize + s.cssStyleSheets.liveSize + s.scripts.liveSize + s.fonts.liveSize;
unsigned decodedSizeTotal = s.images.decodedSize + s.cssStyleSheets.decodedSize + s.scripts.decodedSize + s.fonts.decodedSize;
#if ENABLE(XSLT)
countTotal += s.xslStyleSheets.count;
sizeTotal += s.xslStyleSheets.size;
liveSizeTotal += s.xslStyleSheets.liveSize;
decodedSizeTotal += s.xslStyleSheets.decodedSize;
#endif

WTFLogAlways("%-13s %13d %11.2fKB %11.2fKB %11.2fKB\n", "Total", countTotal, sizeTotal / 1024., liveSizeTotal / 1024., decodedSizeTotal / 1024.);
}

void MemoryCache::dumpLRULists(bool includeLive) const
{
printf("LRU-SP lists in eviction order (Kilobytes decoded, Kilobytes encoded, Access count, Referenced):\n");
WTFLogAlways("LRU-SP lists in eviction order (Kilobytes decoded, Kilobytes encoded, Access count, Referenced):\n");

int size = m_allResources.size();
for (int i = size - 1; i >= 0; i--) {
printf("\n\nList %d: ", i);
WTFLogAlways("\nList %d:\n", i);
for (auto* resource : *m_allResources[i]) {
if (includeLive || !resource->hasClients())
printf("(%.1fK, %.1fK, %uA, %dR); ", resource->decodedSize() / 1024.0f, (resource->encodedSize() + resource->overheadSize()) / 1024.0f, resource->accessCount(), resource->hasClients());
WTFLogAlways(" %.100s %.1fK, %.1fK, accesses: %u, clients: %d\n", resource->url().string().utf8().data(), resource->decodedSize() / 1024.0f, (resource->encodedSize() + resource->overheadSize()) / 1024.0f, resource->accessCount(), resource->numberOfClients());
}
}
}
#endif

} // namespace WebCore
@@ -176,10 +176,9 @@ class MemoryCache {
~MemoryCache(); // Not implemented to make sure nobody accidentally calls delete -- WebCore does not delete singletons.

LRUList& lruListFor(CachedResource&);
#ifndef NDEBUG

void dumpStats();
void dumpLRULists(bool includeLive) const;
#endif

unsigned liveCapacity() const;
unsigned deadCapacity() const;
@@ -190,16 +189,16 @@ class MemoryCache {
CachedResourceMap& ensureSessionResourceMap(PAL::SessionID);
CachedResourceMap* sessionResourceMap(PAL::SessionID) const;

bool m_disabled; // Whether or not the cache is enabled.
bool m_inPruneResources;
bool m_disabled { false };
bool m_inPruneResources { false };

unsigned m_capacity;
unsigned m_minDeadCapacity;
unsigned m_minDeadCapacity { 0 };
unsigned m_maxDeadCapacity;
Seconds m_deadDecodedDataDeletionInterval;

unsigned m_liveSize; // The number of bytes currently consumed by "live" resources in the cache.
unsigned m_deadSize; // The number of bytes currently consumed by "dead" resources in the cache.
unsigned m_liveSize { 0 }; // The number of bytes currently consumed by "live" resources in the cache.
unsigned m_deadSize { 0 }; // The number of bytes currently consumed by "dead" resources in the cache.

// Size-adjusted and popularity-aware LRU list collection for cache objects. This collection can hold
// more resources than the cached resource map, since it can also hold "stale" multiple versions of objects that are
@@ -52,16 +52,35 @@
addSchedulePair(SchedulePair::create([[NSRunLoop currentRunLoop] getCFRunLoop], kCFRunLoopCommonModes));
#endif

#if ENABLE(TREE_DEBUGGING)
static std::once_flag onceFlag;
std::call_once(onceFlag, [] {
#if ENABLE(TREE_DEBUGGING)
PAL::registerNotifyCallback("com.apple.WebKit.showRenderTree", printRenderTreeForLiveDocuments);
PAL::registerNotifyCallback("com.apple.WebKit.showLayerTree", printLayerTreeForLiveDocuments);
#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
PAL::registerNotifyCallback("com.apple.WebKit.showLayoutTree", Layout::printLayoutTreeForLiveDocuments);
#endif
#endif // ENABLE(TREE_DEBUGGING)

PAL::registerNotifyCallback("com.apple.WebKit.showAllDocuments", [] {
unsigned numPages = 0;
Page::forEachPage([&numPages](Page&) {
++numPages;
});

WTFLogAlways("%u live pages:", numPages);

Page::forEachPage([](Page& page) {
const auto* mainFrameDocument = page.mainFrame().document();
WTFLogAlways("Page %p with main document %p %s", &page, mainFrameDocument, mainFrameDocument ? mainFrameDocument->url().string().utf8().data() : "");
});

WTFLogAlways("%u live documents:", Document::allDocuments().size());
for (const auto* document : Document::allDocuments()) {
WTFLogAlways("Document %p %s", document, document->url().string().utf8().data());
}
});
});
#endif
}

void Page::addSchedulePair(Ref<SchedulePair>&& pair)

0 comments on commit 97fb95e

Please sign in to comment.