]> git.saurik.com Git - apple/javascriptcore.git/blob - heap/HeapStatistics.cpp
JavaScriptCore-1218.34.tar.gz
[apple/javascriptcore.git] / heap / HeapStatistics.cpp
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"
30 #include "JSObject.h"
31 #include "Operations.h"
32 #include "Options.h"
33 #include <stdlib.h>
34 #if OS(UNIX)
35 #include <sys/resource.h>
36 #endif
37 #include <wtf/CurrentTime.h>
38 #include <wtf/DataLog.h>
39 #include <wtf/Deque.h>
40
41 namespace JSC {
42
43 double HeapStatistics::s_startTime = 0.0;
44 double HeapStatistics::s_endTime = 0.0;
45 Vector<double>* HeapStatistics::s_pauseTimeStarts = 0;
46 Vector<double>* HeapStatistics::s_pauseTimeEnds = 0;
47
48 #if OS(UNIX)
49
50 void HeapStatistics::initialize()
51 {
52 ASSERT(Options::recordGCPauseTimes());
53 s_startTime = WTF::monotonicallyIncreasingTime();
54 s_pauseTimeStarts = new Vector<double>();
55 s_pauseTimeEnds = new Vector<double>();
56 }
57
58 void HeapStatistics::recordGCPauseTime(double start, double end)
59 {
60 ASSERT(Options::recordGCPauseTimes());
61 ASSERT(s_pauseTimeStarts);
62 ASSERT(s_pauseTimeEnds);
63 s_pauseTimeStarts->append(start);
64 s_pauseTimeEnds->append(end);
65 }
66
67 void HeapStatistics::logStatistics()
68 {
69 struct rusage usage;
70 getrusage(RUSAGE_SELF, &usage);
71 #if USE(CF) || OS(UNIX)
72 char* vmName = getenv("JSVMName");
73 char* suiteName = getenv("JSSuiteName");
74 char* benchmarkName = getenv("JSBenchmarkName");
75 #else
76 #error "The HeapStatistics module is not supported on this platform."
77 #endif
78 if (!vmName || !suiteName || !benchmarkName)
79 dataLogF("HeapStatistics: {\"max_rss\": %ld", usage.ru_maxrss);
80 else
81 dataLogF("HeapStatistics: {\"max_rss\": %ld, \"vm_name\": \"%s\", \"suite_name\": \"%s\", \"benchmark_name\": \"%s\"",
82 usage.ru_maxrss, vmName, suiteName, benchmarkName);
83
84 if (Options::recordGCPauseTimes()) {
85 dataLogF(", \"pause_times\": [");
86 Vector<double>::iterator startIt = s_pauseTimeStarts->begin();
87 Vector<double>::iterator endIt = s_pauseTimeEnds->begin();
88 if (startIt != s_pauseTimeStarts->end() && endIt != s_pauseTimeEnds->end()) {
89 dataLogF("[%f, %f]", *startIt, *endIt);
90 ++startIt;
91 ++endIt;
92 }
93 while (startIt != s_pauseTimeStarts->end() && endIt != s_pauseTimeEnds->end()) {
94 dataLogF(", [%f, %f]", *startIt, *endIt);
95 ++startIt;
96 ++endIt;
97 }
98 dataLogF("], \"start_time\": %f, \"end_time\": %f", s_startTime, s_endTime);
99 }
100 dataLogF("}\n");
101 }
102
103 void HeapStatistics::exitWithFailure()
104 {
105 ASSERT(Options::logHeapStatisticsAtExit());
106 s_endTime = WTF::monotonicallyIncreasingTime();
107 logStatistics();
108 exit(-1);
109 }
110
111 void HeapStatistics::reportSuccess()
112 {
113 ASSERT(Options::logHeapStatisticsAtExit());
114 s_endTime = WTF::monotonicallyIncreasingTime();
115 logStatistics();
116 }
117
118 #else
119
120 void HeapStatistics::initialize()
121 {
122 }
123
124 void HeapStatistics::recordGCPauseTime(double, double)
125 {
126 }
127
128 void HeapStatistics::logStatistics()
129 {
130 }
131
132 void HeapStatistics::exitWithFailure()
133 {
134 }
135
136 void HeapStatistics::reportSuccess()
137 {
138 }
139
140 #endif // OS(UNIX)
141
142 size_t HeapStatistics::parseMemoryAmount(char* s)
143 {
144 size_t multiplier = 1;
145 char* afterS;
146 size_t value = strtol(s, &afterS, 10);
147 char next = afterS[0];
148 switch (next) {
149 case 'K':
150 multiplier = KB;
151 break;
152 case 'M':
153 multiplier = MB;
154 break;
155 case 'G':
156 multiplier = GB;
157 break;
158 default:
159 break;
160 }
161 return value * multiplier;
162 }
163
164 class StorageStatistics : public MarkedBlock::VoidFunctor {
165 public:
166 StorageStatistics();
167
168 void operator()(JSCell*);
169
170 size_t objectWithOutOfLineStorageCount();
171 size_t objectCount();
172
173 size_t storageSize();
174 size_t storageCapacity();
175
176 private:
177 size_t m_objectWithOutOfLineStorageCount;
178 size_t m_objectCount;
179 size_t m_storageSize;
180 size_t m_storageCapacity;
181 };
182
183 inline StorageStatistics::StorageStatistics()
184 : m_objectWithOutOfLineStorageCount(0)
185 , m_objectCount(0)
186 , m_storageSize(0)
187 , m_storageCapacity(0)
188 {
189 }
190
191 inline void StorageStatistics::operator()(JSCell* cell)
192 {
193 if (!cell->isObject())
194 return;
195
196 JSObject* object = jsCast<JSObject*>(cell);
197 if (hasIndexedProperties(object->structure()->indexingType()))
198 return;
199
200 if (object->structure()->isUncacheableDictionary())
201 return;
202
203 ++m_objectCount;
204 if (!object->hasInlineStorage())
205 ++m_objectWithOutOfLineStorageCount;
206 m_storageSize += object->structure()->totalStorageSize() * sizeof(WriteBarrierBase<Unknown>);
207 m_storageCapacity += object->structure()->totalStorageCapacity() * sizeof(WriteBarrierBase<Unknown>);
208 }
209
210 inline size_t StorageStatistics::objectWithOutOfLineStorageCount()
211 {
212 return m_objectWithOutOfLineStorageCount;
213 }
214
215 inline size_t StorageStatistics::objectCount()
216 {
217 return m_objectCount;
218 }
219
220 inline size_t StorageStatistics::storageSize()
221 {
222 return m_storageSize;
223 }
224
225 inline size_t StorageStatistics::storageCapacity()
226 {
227 return m_storageCapacity;
228 }
229
230 void HeapStatistics::showObjectStatistics(Heap* heap)
231 {
232 dataLogF("\n=== Heap Statistics: ===\n");
233 dataLogF("size: %ldkB\n", static_cast<long>(heap->m_sizeAfterLastCollect / KB));
234 dataLogF("capacity: %ldkB\n", static_cast<long>(heap->capacity() / KB));
235 dataLogF("pause time: %lfms\n\n", heap->m_lastGCLength);
236
237 StorageStatistics storageStatistics;
238 heap->m_objectSpace.forEachLiveCell(storageStatistics);
239 dataLogF("wasted .property storage: %ldkB (%ld%%)\n",
240 static_cast<long>(
241 (storageStatistics.storageCapacity() - storageStatistics.storageSize()) / KB),
242 static_cast<long>(
243 (storageStatistics.storageCapacity() - storageStatistics.storageSize()) * 100
244 / storageStatistics.storageCapacity()));
245 dataLogF("objects with out-of-line .property storage: %ld (%ld%%)\n",
246 static_cast<long>(
247 storageStatistics.objectWithOutOfLineStorageCount()),
248 static_cast<long>(
249 storageStatistics.objectWithOutOfLineStorageCount() * 100
250 / storageStatistics.objectCount()));
251 }
252
253 } // namespace JSC