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