]> git.saurik.com Git - apple/javascriptcore.git/blame - heap/HeapStatistics.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / heap / HeapStatistics.cpp
CommitLineData
93a37866
A
1/*
2 * Copyright (C) 2012 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "HeapStatistics.h"
28
29#include "Heap.h"
81345200 30#include "HeapIterationScope.h"
81345200 31#include "JSCInlines.h"
ed1e77d3 32#include "JSObject.h"
93a37866
A
33#include "Options.h"
34#include <stdlib.h>
35#if OS(UNIX)
36#include <sys/resource.h>
37#endif
38#include <wtf/CurrentTime.h>
39#include <wtf/DataLog.h>
40#include <wtf/Deque.h>
41
42namespace JSC {
43
44double HeapStatistics::s_startTime = 0.0;
45double HeapStatistics::s_endTime = 0.0;
46Vector<double>* HeapStatistics::s_pauseTimeStarts = 0;
47Vector<double>* HeapStatistics::s_pauseTimeEnds = 0;
48
49#if OS(UNIX)
50
51void HeapStatistics::initialize()
52{
53 ASSERT(Options::recordGCPauseTimes());
54 s_startTime = WTF::monotonicallyIncreasingTime();
55 s_pauseTimeStarts = new Vector<double>();
56 s_pauseTimeEnds = new Vector<double>();
57}
58
59void HeapStatistics::recordGCPauseTime(double start, double end)
60{
61 ASSERT(Options::recordGCPauseTimes());
62 ASSERT(s_pauseTimeStarts);
63 ASSERT(s_pauseTimeEnds);
64 s_pauseTimeStarts->append(start);
65 s_pauseTimeEnds->append(end);
66}
67
68void HeapStatistics::logStatistics()
69{
70 struct rusage usage;
71 getrusage(RUSAGE_SELF, &usage);
72#if USE(CF) || OS(UNIX)
73 char* vmName = getenv("JSVMName");
74 char* suiteName = getenv("JSSuiteName");
75 char* benchmarkName = getenv("JSBenchmarkName");
76#else
77#error "The HeapStatistics module is not supported on this platform."
78#endif
79 if (!vmName || !suiteName || !benchmarkName)
80 dataLogF("HeapStatistics: {\"max_rss\": %ld", usage.ru_maxrss);
81 else
82 dataLogF("HeapStatistics: {\"max_rss\": %ld, \"vm_name\": \"%s\", \"suite_name\": \"%s\", \"benchmark_name\": \"%s\"",
83 usage.ru_maxrss, vmName, suiteName, benchmarkName);
84
85 if (Options::recordGCPauseTimes()) {
86 dataLogF(", \"pause_times\": [");
87 Vector<double>::iterator startIt = s_pauseTimeStarts->begin();
88 Vector<double>::iterator endIt = s_pauseTimeEnds->begin();
89 if (startIt != s_pauseTimeStarts->end() && endIt != s_pauseTimeEnds->end()) {
90 dataLogF("[%f, %f]", *startIt, *endIt);
91 ++startIt;
92 ++endIt;
93 }
94 while (startIt != s_pauseTimeStarts->end() && endIt != s_pauseTimeEnds->end()) {
95 dataLogF(", [%f, %f]", *startIt, *endIt);
96 ++startIt;
97 ++endIt;
98 }
99 dataLogF("], \"start_time\": %f, \"end_time\": %f", s_startTime, s_endTime);
100 }
101 dataLogF("}\n");
102}
103
104void HeapStatistics::exitWithFailure()
105{
106 ASSERT(Options::logHeapStatisticsAtExit());
107 s_endTime = WTF::monotonicallyIncreasingTime();
108 logStatistics();
109 exit(-1);
110}
111
112void HeapStatistics::reportSuccess()
113{
114 ASSERT(Options::logHeapStatisticsAtExit());
115 s_endTime = WTF::monotonicallyIncreasingTime();
116 logStatistics();
117}
118
119#else
120
121void HeapStatistics::initialize()
122{
123}
124
125void HeapStatistics::recordGCPauseTime(double, double)
126{
127}
128
129void HeapStatistics::logStatistics()
130{
131}
132
133void HeapStatistics::exitWithFailure()
134{
ed1e77d3 135 exit(-1);
93a37866
A
136}
137
138void HeapStatistics::reportSuccess()
139{
140}
141
142#endif // OS(UNIX)
143
144size_t HeapStatistics::parseMemoryAmount(char* s)
145{
146 size_t multiplier = 1;
147 char* afterS;
148 size_t value = strtol(s, &afterS, 10);
149 char next = afterS[0];
150 switch (next) {
151 case 'K':
152 multiplier = KB;
153 break;
154 case 'M':
155 multiplier = MB;
156 break;
157 case 'G':
158 multiplier = GB;
159 break;
160 default:
161 break;
162 }
163 return value * multiplier;
164}
165
166class StorageStatistics : public MarkedBlock::VoidFunctor {
167public:
168 StorageStatistics();
169
ed1e77d3 170 IterationStatus operator()(JSCell*);
93a37866
A
171
172 size_t objectWithOutOfLineStorageCount();
173 size_t objectCount();
174
175 size_t storageSize();
176 size_t storageCapacity();
177
178private:
ed1e77d3
A
179 void visit(JSCell*);
180
93a37866
A
181 size_t m_objectWithOutOfLineStorageCount;
182 size_t m_objectCount;
183 size_t m_storageSize;
184 size_t m_storageCapacity;
185};
186
187inline StorageStatistics::StorageStatistics()
188 : m_objectWithOutOfLineStorageCount(0)
189 , m_objectCount(0)
190 , m_storageSize(0)
191 , m_storageCapacity(0)
192{
193}
194
ed1e77d3 195inline void StorageStatistics::visit(JSCell* cell)
93a37866
A
196{
197 if (!cell->isObject())
198 return;
199
200 JSObject* object = jsCast<JSObject*>(cell);
81345200 201 if (hasIndexedProperties(object->indexingType()))
93a37866
A
202 return;
203
204 if (object->structure()->isUncacheableDictionary())
205 return;
206
207 ++m_objectCount;
208 if (!object->hasInlineStorage())
209 ++m_objectWithOutOfLineStorageCount;
210 m_storageSize += object->structure()->totalStorageSize() * sizeof(WriteBarrierBase<Unknown>);
211 m_storageCapacity += object->structure()->totalStorageCapacity() * sizeof(WriteBarrierBase<Unknown>);
212}
213
ed1e77d3
A
214inline IterationStatus StorageStatistics::operator()(JSCell* cell)
215{
216 visit(cell);
217 return IterationStatus::Continue;
218}
219
93a37866
A
220inline size_t StorageStatistics::objectWithOutOfLineStorageCount()
221{
222 return m_objectWithOutOfLineStorageCount;
223}
224
225inline size_t StorageStatistics::objectCount()
226{
227 return m_objectCount;
228}
229
230inline size_t StorageStatistics::storageSize()
231{
232 return m_storageSize;
233}
234
235inline size_t StorageStatistics::storageCapacity()
236{
237 return m_storageCapacity;
238}
239
240void HeapStatistics::showObjectStatistics(Heap* heap)
241{
242 dataLogF("\n=== Heap Statistics: ===\n");
243 dataLogF("size: %ldkB\n", static_cast<long>(heap->m_sizeAfterLastCollect / KB));
244 dataLogF("capacity: %ldkB\n", static_cast<long>(heap->capacity() / KB));
ed1e77d3 245 dataLogF("pause time: %lfs\n\n", heap->m_lastFullGCLength);
93a37866
A
246
247 StorageStatistics storageStatistics;
81345200
A
248 {
249 HeapIterationScope iterationScope(*heap);
250 heap->m_objectSpace.forEachLiveCell(iterationScope, storageStatistics);
251 }
ed1e77d3
A
252 long wastedPropertyStorageBytes = 0;
253 long wastedPropertyStoragePercent = 0;
254 long objectWithOutOfLineStorageCount = 0;
255 long objectsWithOutOfLineStoragePercent = 0;
256 if ((storageStatistics.storageCapacity() > 0) && (storageStatistics.objectCount() > 0)) {
257 wastedPropertyStorageBytes = static_cast<long>((storageStatistics.storageCapacity() - storageStatistics.storageSize()) / KB);
258 wastedPropertyStoragePercent = static_cast<long>(
259 (storageStatistics.storageCapacity() - storageStatistics.storageSize()) * 100 / storageStatistics.storageCapacity());
260 objectWithOutOfLineStorageCount = static_cast<long>(storageStatistics.objectWithOutOfLineStorageCount());
261 objectsWithOutOfLineStoragePercent = objectWithOutOfLineStorageCount * 100 / storageStatistics.objectCount();
262 }
263 dataLogF("wasted .property storage: %ldkB (%ld%%)\n", wastedPropertyStorageBytes, wastedPropertyStoragePercent);
264 dataLogF("objects with out-of-line .property storage: %ld (%ld%%)\n", objectWithOutOfLineStorageCount, objectsWithOutOfLineStoragePercent);
93a37866
A
265}
266
267} // namespace JSC