Ignore:
Timestamp:
Oct 5, 2012, 10:35:49 AM (13 years ago)
Author:
[email protected]
Message:

JSC should have a way to gather and log Heap memory use and pause times
https://bugs.webkit.org/show_bug.cgi?id=98431

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

In order to improve our infrastructure for benchmark-driven development, we should
have a centralized method of gathering and logging various statistics about the state
of the JS heap. This would allow us to create and to use other tools to analyze the
output of the VM after running various workloads.

The first two statistics that might be interesting is memory use by JSC and GC pause
times. We can control whether this recording happens through the use of the Options
class, allowing us to either use environment variables or command line flags.

(JSC::Heap::collect): If we finish a collection and are still over our set GC heap size,
we end the program immediately and report an error. Also added recording of pause times.

  • heap/Heap.h:

(Heap):
(JSC::Heap::shouldCollect): When we set a specific GC heap size through Options, we
ignore all other heuristics on when we should collect and instead only ask if we're
greater than the amount specified in the Option value. This allows us to view time/memory
tradeoffs more clearly.

  • heap/HeapStatistics.cpp: Added.

(JSC):
(JSC::HeapStatistics::initialize):
(JSC::HeapStatistics::recordGCPauseTime):
(JSC::HeapStatistics::logStatistics):
(JSC::HeapStatistics::exitWithFailure):
(JSC::HeapStatistics::reportSuccess):
(JSC::HeapStatistics::parseMemoryAmount):
(StorageStatistics):
(JSC::StorageStatistics::StorageStatistics):
(JSC::StorageStatistics::operator()):
(JSC::StorageStatistics::objectWithOutOfLineStorageCount):
(JSC::StorageStatistics::objectCount):
(JSC::StorageStatistics::storageSize):
(JSC::StorageStatistics::storageCapacity):
(JSC::HeapStatistics::showObjectStatistics): Moved the old showHeapStatistics (renamed to showObjectStatistics)
to try to start collecting our various memory statistics gathering/reporting mechanisms scattered throughout the
codebase into one place.

  • heap/HeapStatistics.h: Added.

(JSC):
(HeapStatistics):

  • jsc.cpp:

(main):

  • runtime/InitializeThreading.cpp:

(JSC::initializeThreadingOnce): We need to initialize our data structures for recording
statistics if necessary.

  • runtime/Options.cpp: Add new Options for the various types of statistics we'll be gathering.

(JSC::parse):
(JSC):
(JSC::Options::initialize): Initialize the various new options using environment variables.
(JSC::Options::dumpOption):

  • runtime/Options.h:

(JSC):

Tools:

  • DumpRenderTree/mac/DumpRenderTree.mm:

(main): Added a check as to whether we should dump our JSC Heap statistics on exit.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/heap/Heap.cpp

    r130303 r130520  
    2828#include "GCActivityCallback.h"
    2929#include "HeapRootVisitor.h"
     30#include "HeapStatistics.h"
    3031#include "IncrementalSweeper.h"
    3132#include "Interpreter.h"
     
    234235{
    235236    return m_typeCountSet.release();
    236 }
    237 
    238 class StorageStatistics : public MarkedBlock::VoidFunctor {
    239 public:
    240     StorageStatistics();
    241 
    242     void operator()(JSCell*);
    243 
    244     size_t objectWithOutOfLineStorageCount();
    245     size_t objectCount();
    246 
    247     size_t storageSize();
    248     size_t storageCapacity();
    249 
    250 private:
    251     size_t m_objectWithOutOfLineStorageCount;
    252     size_t m_objectCount;
    253     size_t m_storageSize;
    254     size_t m_storageCapacity;
    255 };
    256 
    257 inline StorageStatistics::StorageStatistics()
    258     : m_objectWithOutOfLineStorageCount(0)
    259     , m_objectCount(0)
    260     , m_storageSize(0)
    261     , m_storageCapacity(0)
    262 {
    263 }
    264 
    265 inline void StorageStatistics::operator()(JSCell* cell)
    266 {
    267     if (!cell->isObject())
    268         return;
    269 
    270     JSObject* object = jsCast<JSObject*>(cell);
    271     if (hasIndexedProperties(object->structure()->indexingType()))
    272         return;
    273 
    274     if (object->structure()->isUncacheableDictionary())
    275         return;
    276 
    277     ++m_objectCount;
    278     if (!object->hasInlineStorage())
    279         ++m_objectWithOutOfLineStorageCount;
    280     m_storageSize += object->structure()->totalStorageSize() * sizeof(WriteBarrierBase<Unknown>);
    281     m_storageCapacity += object->structure()->totalStorageCapacity() * sizeof(WriteBarrierBase<Unknown>);
    282 }
    283 
    284 inline size_t StorageStatistics::objectWithOutOfLineStorageCount()
    285 {
    286     return m_objectWithOutOfLineStorageCount;
    287 }
    288 
    289 inline size_t StorageStatistics::objectCount()
    290 {
    291     return m_objectCount;
    292 }
    293 
    294 
    295 inline size_t StorageStatistics::storageSize()
    296 {
    297     return m_storageSize;
    298 }
    299 
    300 
    301 inline size_t StorageStatistics::storageCapacity()
    302 {
    303     return m_storageCapacity;
    304237}
    305238
     
    832765   
    833766    size_t currentHeapSize = size();
     767    if (Options::gcMaxHeapSize() && currentHeapSize > Options::gcMaxHeapSize())
     768        HeapStatistics::exitWithFailure();
     769
    834770    if (fullGC) {
    835771        m_sizeAfterLastCollect = currentHeapSize;
     
    845781    m_lastGCLength = lastGCEndTime - lastGCStartTime;
    846782
     783    if (Options::recordGCPauseTimes())
     784        HeapStatistics::recordGCPauseTime(lastGCStartTime, lastGCEndTime);
    847785    if (m_operationInProgress != Collection)
    848786        CRASH();
     
    856794        markDeadObjects();
    857795
    858     if (Options::showHeapStatistics())
    859         showStatistics();
    860 }
    861 
    862 void Heap::showStatistics()
    863 {
    864     dataLog("\n=== Heap Statistics: ===\n");
    865     dataLog("size: %ldkB\n", static_cast<long>(m_sizeAfterLastCollect / KB));
    866     dataLog("capacity: %ldkB\n", static_cast<long>(capacity() / KB));
    867     dataLog("pause time: %lfms\n\n", m_lastGCLength);
    868 
    869     StorageStatistics storageStatistics;
    870     m_objectSpace.forEachLiveCell(storageStatistics);
    871     dataLog("wasted .property storage: %ldkB (%ld%%)\n",
    872         static_cast<long>(
    873             (storageStatistics.storageCapacity() - storageStatistics.storageSize()) / KB),
    874         static_cast<long>(
    875             (storageStatistics.storageCapacity() - storageStatistics.storageSize()) * 100
    876                 / storageStatistics.storageCapacity()));
    877     dataLog("objects with out-of-line .property storage: %ld (%ld%%)\n",
    878         static_cast<long>(
    879             storageStatistics.objectWithOutOfLineStorageCount()),
    880         static_cast<long>(
    881             storageStatistics.objectWithOutOfLineStorageCount() * 100
    882                 / storageStatistics.objectCount()));
     796    if (Options::showObjectStatistics())
     797        HeapStatistics::showObjectStatistics(this);
    883798}
    884799
Note: See TracChangeset for help on using the changeset viewer.