diff options
| author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2015-10-15 09:45:50 +0000 |
|---|---|---|
| committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2015-10-15 09:45:50 +0000 |
| commit | e15dd966d523731101f70ccf768bba12435a0208 (patch) | |
| tree | ae9cb828a24ded2585a41af3f21411523b47897d /Source/JavaScriptCore/heap/HeapStatistics.cpp | |
| download | WebKitGtk-tarball-e15dd966d523731101f70ccf768bba12435a0208.tar.gz | |
webkitgtk-2.10.2webkitgtk-2.10.2
Diffstat (limited to 'Source/JavaScriptCore/heap/HeapStatistics.cpp')
| -rw-r--r-- | Source/JavaScriptCore/heap/HeapStatistics.cpp | 267 |
1 files changed, 267 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/heap/HeapStatistics.cpp b/Source/JavaScriptCore/heap/HeapStatistics.cpp new file mode 100644 index 000000000..bc5465fb9 --- /dev/null +++ b/Source/JavaScriptCore/heap/HeapStatistics.cpp @@ -0,0 +1,267 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "HeapStatistics.h" + +#include "Heap.h" +#include "HeapIterationScope.h" +#include "JSCInlines.h" +#include "JSObject.h" +#include "Options.h" +#include <stdlib.h> +#if OS(UNIX) +#include <sys/resource.h> +#endif +#include <wtf/CurrentTime.h> +#include <wtf/DataLog.h> +#include <wtf/Deque.h> + +namespace JSC { + +double HeapStatistics::s_startTime = 0.0; +double HeapStatistics::s_endTime = 0.0; +Vector<double>* HeapStatistics::s_pauseTimeStarts = 0; +Vector<double>* HeapStatistics::s_pauseTimeEnds = 0; + +#if OS(UNIX) + +void HeapStatistics::initialize() +{ + ASSERT(Options::recordGCPauseTimes()); + s_startTime = WTF::monotonicallyIncreasingTime(); + s_pauseTimeStarts = new Vector<double>(); + s_pauseTimeEnds = new Vector<double>(); +} + +void HeapStatistics::recordGCPauseTime(double start, double end) +{ + ASSERT(Options::recordGCPauseTimes()); + ASSERT(s_pauseTimeStarts); + ASSERT(s_pauseTimeEnds); + s_pauseTimeStarts->append(start); + s_pauseTimeEnds->append(end); +} + +void HeapStatistics::logStatistics() +{ + struct rusage usage; + getrusage(RUSAGE_SELF, &usage); +#if USE(CF) || OS(UNIX) + char* vmName = getenv("JSVMName"); + char* suiteName = getenv("JSSuiteName"); + char* benchmarkName = getenv("JSBenchmarkName"); +#else +#error "The HeapStatistics module is not supported on this platform." +#endif + if (!vmName || !suiteName || !benchmarkName) + dataLogF("HeapStatistics: {\"max_rss\": %ld", usage.ru_maxrss); + else + dataLogF("HeapStatistics: {\"max_rss\": %ld, \"vm_name\": \"%s\", \"suite_name\": \"%s\", \"benchmark_name\": \"%s\"", + usage.ru_maxrss, vmName, suiteName, benchmarkName); + + if (Options::recordGCPauseTimes()) { + dataLogF(", \"pause_times\": ["); + Vector<double>::iterator startIt = s_pauseTimeStarts->begin(); + Vector<double>::iterator endIt = s_pauseTimeEnds->begin(); + if (startIt != s_pauseTimeStarts->end() && endIt != s_pauseTimeEnds->end()) { + dataLogF("[%f, %f]", *startIt, *endIt); + ++startIt; + ++endIt; + } + while (startIt != s_pauseTimeStarts->end() && endIt != s_pauseTimeEnds->end()) { + dataLogF(", [%f, %f]", *startIt, *endIt); + ++startIt; + ++endIt; + } + dataLogF("], \"start_time\": %f, \"end_time\": %f", s_startTime, s_endTime); + } + dataLogF("}\n"); +} + +void HeapStatistics::exitWithFailure() +{ + ASSERT(Options::logHeapStatisticsAtExit()); + s_endTime = WTF::monotonicallyIncreasingTime(); + logStatistics(); + exit(-1); +} + +void HeapStatistics::reportSuccess() +{ + ASSERT(Options::logHeapStatisticsAtExit()); + s_endTime = WTF::monotonicallyIncreasingTime(); + logStatistics(); +} + +#else + +void HeapStatistics::initialize() +{ +} + +void HeapStatistics::recordGCPauseTime(double, double) +{ +} + +void HeapStatistics::logStatistics() +{ +} + +void HeapStatistics::exitWithFailure() +{ + exit(-1); +} + +void HeapStatistics::reportSuccess() +{ +} + +#endif // OS(UNIX) + +size_t HeapStatistics::parseMemoryAmount(char* s) +{ + size_t multiplier = 1; + char* afterS; + size_t value = strtol(s, &afterS, 10); + char next = afterS[0]; + switch (next) { + case 'K': + multiplier = KB; + break; + case 'M': + multiplier = MB; + break; + case 'G': + multiplier = GB; + break; + default: + break; + } + return value * multiplier; +} + +class StorageStatistics : public MarkedBlock::VoidFunctor { +public: + StorageStatistics(); + + IterationStatus operator()(JSCell*); + + size_t objectWithOutOfLineStorageCount(); + size_t objectCount(); + + size_t storageSize(); + size_t storageCapacity(); + +private: + void visit(JSCell*); + + size_t m_objectWithOutOfLineStorageCount; + size_t m_objectCount; + size_t m_storageSize; + size_t m_storageCapacity; +}; + +inline StorageStatistics::StorageStatistics() + : m_objectWithOutOfLineStorageCount(0) + , m_objectCount(0) + , m_storageSize(0) + , m_storageCapacity(0) +{ +} + +inline void StorageStatistics::visit(JSCell* cell) +{ + if (!cell->isObject()) + return; + + JSObject* object = jsCast<JSObject*>(cell); + if (hasIndexedProperties(object->indexingType())) + return; + + if (object->structure()->isUncacheableDictionary()) + return; + + ++m_objectCount; + if (!object->hasInlineStorage()) + ++m_objectWithOutOfLineStorageCount; + m_storageSize += object->structure()->totalStorageSize() * sizeof(WriteBarrierBase<Unknown>); + m_storageCapacity += object->structure()->totalStorageCapacity() * sizeof(WriteBarrierBase<Unknown>); +} + +inline IterationStatus StorageStatistics::operator()(JSCell* cell) +{ + visit(cell); + return IterationStatus::Continue; +} + +inline size_t StorageStatistics::objectWithOutOfLineStorageCount() +{ + return m_objectWithOutOfLineStorageCount; +} + +inline size_t StorageStatistics::objectCount() +{ + return m_objectCount; +} + +inline size_t StorageStatistics::storageSize() +{ + return m_storageSize; +} + +inline size_t StorageStatistics::storageCapacity() +{ + return m_storageCapacity; +} + +void HeapStatistics::showObjectStatistics(Heap* heap) +{ + dataLogF("\n=== Heap Statistics: ===\n"); + dataLogF("size: %ldkB\n", static_cast<long>(heap->m_sizeAfterLastCollect / KB)); + dataLogF("capacity: %ldkB\n", static_cast<long>(heap->capacity() / KB)); + dataLogF("pause time: %lfs\n\n", heap->m_lastFullGCLength); + + StorageStatistics storageStatistics; + { + HeapIterationScope iterationScope(*heap); + heap->m_objectSpace.forEachLiveCell(iterationScope, storageStatistics); + } + long wastedPropertyStorageBytes = 0; + long wastedPropertyStoragePercent = 0; + long objectWithOutOfLineStorageCount = 0; + long objectsWithOutOfLineStoragePercent = 0; + if ((storageStatistics.storageCapacity() > 0) && (storageStatistics.objectCount() > 0)) { + wastedPropertyStorageBytes = static_cast<long>((storageStatistics.storageCapacity() - storageStatistics.storageSize()) / KB); + wastedPropertyStoragePercent = static_cast<long>( + (storageStatistics.storageCapacity() - storageStatistics.storageSize()) * 100 / storageStatistics.storageCapacity()); + objectWithOutOfLineStorageCount = static_cast<long>(storageStatistics.objectWithOutOfLineStorageCount()); + objectsWithOutOfLineStoragePercent = objectWithOutOfLineStorageCount * 100 / storageStatistics.objectCount(); + } + dataLogF("wasted .property storage: %ldkB (%ld%%)\n", wastedPropertyStorageBytes, wastedPropertyStoragePercent); + dataLogF("objects with out-of-line .property storage: %ld (%ld%%)\n", objectWithOutOfLineStorageCount, objectsWithOutOfLineStoragePercent); +} + +} // namespace JSC |
