Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(688)

Unified Diff: Source/platform/heap/Heap.cpp

Issue 717923005: Profile FreeList Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Rebased Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/platform/heap/Heap.h ('k') | Source/platform/heap/ThreadState.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/platform/heap/Heap.cpp
diff --git a/Source/platform/heap/Heap.cpp b/Source/platform/heap/Heap.cpp
index 2163e15d963b3259f0c6f7654ee177703cde54f8..3a7ecf0bfd02bd5179ddb522b8d7af925108b9e1 100644
--- a/Source/platform/heap/Heap.cpp
+++ b/Source/platform/heap/Heap.cpp
@@ -50,7 +50,7 @@
#include <stdio.h>
#include <utility>
#endif
-#if ENABLE(GC_PROFILE_HEAP)
+#if ENABLE(GC_PROFILE_HEAP) || ENABLE(GC_PROFILE_FREE_LIST) || ENABLE(GC_PROFILE_MARKING)
#include "platform/TracedValue.h"
#endif
@@ -63,6 +63,36 @@
namespace blink {
+struct AgeHistogram {
+ int data[8];
+};
+
+typedef HashMap<String, AgeHistogram> ObjectAgeMap;
+
+static ObjectAgeMap& uom()
+{
+ static ObjectAgeMap uomap;
+ return uomap;
+}
+
+static Mutex& uomMutex()
+{
+ AtomicallyInitializedStaticReference(Mutex, mutex, new Mutex);
+ return mutex;
+}
+
+static ObjectAgeMap& mom()
+{
+ static ObjectAgeMap momap;
+ return momap;
+}
+
+static Mutex& momMutex()
+{
+ AtomicallyInitializedStaticReference(Mutex, mutex, new Mutex);
+ return mutex;
+}
+
#if ENABLE(GC_PROFILE_MARKING)
static String classOf(const void* object)
{
@@ -543,6 +573,11 @@ ThreadHeap::ThreadHeap(ThreadState* state, int index)
: m_currentAllocationPoint(nullptr)
, m_remainingAllocationSize(0)
, m_lastRemainingAllocationSize(0)
+#if ENABLE(GC_PROFILE_FREE_LIST)
+ , m_totalAllocationSize(0.0)
+ , m_allocationCount(0)
+ , m_inlineAllocationCount(0)
+#endif
, m_firstPage(nullptr)
, m_firstLargeObject(nullptr)
, m_firstUnsweptPage(nullptr)
@@ -606,6 +641,10 @@ void ThreadHeap::setAllocationPoint(Address point, size_t size)
ASSERT(size <= static_cast<HeapPage*>(page)->payloadSize());
}
#endif
+#if ENABLE(GC_PROFILE_FREE_LIST)
+ m_allocationPointSizeSum += size;
+ ++m_setAllocationPointCount;
+#endif
if (hasCurrentAllocationArea())
addToFreeList(currentAllocationPoint(), remainingAllocationSize());
updateRemainingAllocationSize();
@@ -615,6 +654,9 @@ void ThreadHeap::setAllocationPoint(Address point, size_t size)
Address ThreadHeap::outOfLineAllocate(size_t allocationSize, size_t gcInfoIndex)
{
+#if ENABLE(GC_PROFILE_FREE_LIST)
+ m_threadState->snapshotFreeListIfNecessary();
+#endif
ASSERT(allocationSize > remainingAllocationSize());
ASSERT(allocationSize >= allocationGranularity);
@@ -857,7 +899,9 @@ static bool isLargeObjectAligned(LargeObject* largeObject, Address address)
// for the guard page).
return reinterpret_cast<Address>(largeObject) - WTF::kSystemPageSize == roundToBlinkPageStart(reinterpret_cast<Address>(largeObject));
}
+#endif
+#if ENABLE(ASSERT) || ENABLE(GC_PROFILE_MARKING)
BaseHeapPage* ThreadHeap::findPageFromAddress(Address address)
{
for (HeapPage* page = m_firstPage; page; page = page->next()) {
@@ -882,6 +926,44 @@ BaseHeapPage* ThreadHeap::findPageFromAddress(Address address)
}
#endif
+#if ENABLE(GC_PROFILE_FREE_LIST)
+void ThreadHeap::snapshotFreeList(TracedValue* json)
+{
+ json->setDouble("totalAllocationSize", m_totalAllocationSize);
+ json->setDouble("inlineAllocationRate", static_cast<double>(m_inlineAllocationCount) / m_allocationCount);
+ json->setInteger("inlineAllocationCount", m_inlineAllocationCount);
+ json->setInteger("allocationCount", m_allocationCount);
+ if (m_setAllocationPointCount > 0) {
+ json->setDouble("averageAllocationPointSize", static_cast<double>(m_allocationPointSizeSum) / m_setAllocationPointCount);
+ }
+ m_allocationPointSizeSum = 0;
+ m_setAllocationPointCount = 0;
+ size_t pageCount = 0;
+ size_t totalPageSize = 0;
+ for (HeapPage* page = m_firstPage; page; page = page->next()) {
+ ++pageCount;
+ totalPageSize += page->payloadSize();
+ }
+ json->setInteger("pageCount", pageCount);
+ json->setInteger("totalPageSize", totalPageSize);
+ size_t bucketSizes[blinkPageSizeLog2];
+ size_t bucketTotalSizes[blinkPageSizeLog2];
+ size_t freeSize = 0;
+ m_freeList.countBucketSizes(bucketSizes, bucketTotalSizes, &freeSize);
+ json->setInteger("freeSize", freeSize);
+ json->beginArray("bucketSizes");
+ for (size_t i = 0; i < blinkPageSizeLog2; ++i) {
+ json->pushInteger(bucketSizes[i]);
+ }
+ json->endArray();
+ json->beginArray("bucketTotalSizes");
+ for (size_t i = 0; i < blinkPageSizeLog2; ++i) {
+ json->pushInteger(bucketTotalSizes[i]);
+ }
+ json->endArray();
+}
+#endif
+
#if ENABLE(GC_PROFILE_HEAP)
#define GC_PROFILE_HEAP_PAGE_SNAPSHOT_THRESHOLD 0
void ThreadHeap::snapshot(TracedValue* json, ThreadState::SnapshotInfo* info)
@@ -949,6 +1031,24 @@ void FreeList::addToFreeList(Address address, size_t size)
m_biggestFreeListIndex = index;
}
+#if ENABLE(GC_PROFILE_FREE_LIST)
+void FreeList::countBucketSizes(size_t sizes[], size_t totalSizes[], size_t* freeSize) const
+{
+ *freeSize = 0;
+ for (size_t i = 0; i < blinkPageSizeLog2; i++) {
+ sizes[i] = 0;
+ totalSizes[i] = 0;
+ FreeListEntry* entry = m_freeLists[i];
+ while (entry) {
+ ++sizes[i];
+ *freeSize += entry->size();
+ totalSizes[i] += entry->size();
+ entry = entry->next();
+ }
+ }
+}
+#endif
+
bool ThreadHeap::expandObject(HeapObjectHeader* header, size_t newSize)
{
// It's possible that Vector requests a smaller expanded size because
@@ -1762,6 +1862,32 @@ size_t LargeObject::objectPayloadSizeForTesting()
return payloadSize();
}
+void HeapPage::countUnmarkedObjects()
+{
+ MutexLocker locker(uomMutex());
+ for (Address headerAddress = payload(); headerAddress < payloadEnd(); ) {
+ HeapObjectHeader* header = reinterpret_cast<HeapObjectHeader*>(headerAddress);
+ ASSERT(header->size() < blinkPagePayloadSize());
+
+ if (!header->isFree() && !header->isMarked()) {
+ String className(classOf(header->payload()));
+ ObjectAgeMap::AddResult result = uom().add(className, AgeHistogram());
+ result.storedValue->value.data[header->age()]++;
+ }
+ headerAddress += header->size();
+ }
+}
+
+#if ENABLE(GC_PROFILE_MARKING)
+const GCInfo* LargeObject::findGCInfo(Address address)
+{
+ if (!containedInObjectPayload(address))
+ return nullptr;
+ HeapObjectHeader* header = heapObjectHeader();
+ return Heap::gcInfo(header->gcInfoIndex());
+}
+#endif
+
#if ENABLE(GC_PROFILE_HEAP)
void LargeObject::snapshot(TracedValue* json, ThreadState::SnapshotInfo* info)
{
@@ -1921,7 +2047,7 @@ public:
void reportStats()
{
fprintf(stderr, "\n---------- AFTER MARKING -------------------\n");
- for (LiveObjectMap::iterator it = currentlyLive().begin(), end = currentlyLive().payloadEnd(); it != end; ++it) {
+ for (LiveObjectMap::iterator it = currentlyLive().begin(), end = currentlyLive().end(); it != end; ++it) {
fprintf(stderr, "%s %u", it->key.ascii().data(), it->value.size());
if (it->key == "blink::Document")
@@ -1938,13 +2064,28 @@ public:
}
}
+ void reportMarkingStats()
+ {
+ MutexLocker locker(momMutex());
+ RefPtr<TracedValue> json = TracedValue::create();
+ for (ObjectAgeMap::iterator it = mom().begin(), end = mom().end(); it != end; ++it) {
+ json->beginArray(it->key.ascii().data());
+ for (size_t i = 0; i < 8; ++i) {
+ json->pushInteger(it->value.data[i]);
+ }
+ json->endArray();
+ }
+ TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID("blink_gc", "MarkingStats", (unsigned long long)0, json.release());
+ mom().clear();
+ }
+
static void reportStillAlive(LiveObjectSet current, LiveObjectSet previous)
{
int count = 0;
fprintf(stderr, " [previously %u]", previous.size());
for (uintptr_t object : current) {
- if (previous.find(object) == previous.payloadEnd())
+ if (previous.find(object) == previous.end())
continue;
count++;
}
@@ -1954,7 +2095,7 @@ public:
fprintf(stderr, " {survived 2GCs %d: ", count);
for (uintptr_t object : current) {
- if (previous.find(object) == previous.payloadEnd())
+ if (previous.find(object) == previous.end())
continue;
fprintf(stderr, "%ld", object);
if (--count)
@@ -1967,10 +2108,10 @@ public:
static void dumpPathToObjectFromObjectGraph(const ObjectGraph& graph, uintptr_t target)
{
ObjectGraph::const_iterator it = graph.find(target);
- if (it == graph.payloadEnd())
+ if (it == graph.end())
return;
fprintf(stderr, "Path to %lx of %s\n", target, classOf(reinterpret_cast<const void*>(target)).ascii().data());
- while (it != graph.payloadEnd()) {
+ while (it != graph.end()) {
fprintf(stderr, "<- %lx of %s\n", it->value.first, it->value.second.utf8().data());
it = graph.find(it->value.first);
}
@@ -2284,6 +2425,21 @@ void Heap::preGC()
state->preGC();
}
+void Heap::reportSweepingStats()
+{
+ MutexLocker locker(uomMutex());
+ RefPtr<TracedValue> json = TracedValue::create();
+ for (ObjectAgeMap::iterator it = uom().begin(), end = uom().end(); it != end; ++it) {
+ json->beginArray(it->key.ascii().data());
+ for (size_t i = 0; i < 8; ++i) {
+ json->pushInteger(it->value.data[i]);
+ }
+ json->endArray();
+ }
+ TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID("blink_gc", "SweepingStats", (unsigned long long)0, json.release());
+ uom().clear();
+}
+
void Heap::postGC(ThreadState::GCType gcType)
{
ASSERT(ThreadState::current()->isInGC());
@@ -2296,6 +2452,10 @@ void Heap::collectGarbage(ThreadState::StackState stackState, ThreadState::GCTyp
ThreadState* state = ThreadState::current();
state->setGCState(ThreadState::StoppingOtherThreads);
+#if ENABLE(GC_PROFILE_FREE_LIST)
+ state->snapshotFreeListIfNecessary();
+#endif
+
GCScope gcScope(stackState);
// Check if we successfully parked the other threads. If not we bail out of
// the GC.
@@ -2357,7 +2517,8 @@ void Heap::collectGarbage(ThreadState::StackState stackState, ThreadState::GCTyp
postGC(gcType);
#if ENABLE(GC_PROFILE_MARKING)
- static_cast<MarkingVisitor<GlobalMarking>*>(s_markingVisitor)->reportStats();
+ //static_cast<MarkingVisitor<GlobalMarking>*>(s_markingVisitor)->reportStats();
+ static_cast<MarkingVisitor<GlobalMarking>*>(s_markingVisitor)->reportMarkingStats();
#endif
if (Platform::current()) {
« no previous file with comments | « Source/platform/heap/Heap.h ('k') | Source/platform/heap/ThreadState.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698