1/*
2 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
3 * Copyright (C) 2012 Samsung Electronics
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "WebMemorySampler.h"
28
29#if ENABLE(MEMORY_SAMPLER)
30
31#include <JavaScriptCore/JSCInlines.h>
32#include <JavaScriptCore/JSLock.h>
33#include <JavaScriptCore/MemoryStatistics.h>
34#include <WebCore/CommonVM.h>
35#include <WebCore/JSDOMWindow.h>
36#include <WebCore/NotImplemented.h>
37#include <string.h>
38#include <sys/sysinfo.h>
39#include <wtf/WallTime.h>
40#include <wtf/linux/CurrentProcessMemoryStatus.h>
41#include <wtf/text/WTFString.h>
42
43namespace WebKit {
44
45using namespace JSC;
46using namespace WebCore;
47
48static const unsigned int maxBuffer = 128;
49static const unsigned int maxProcessPath = 35;
50
51static inline String nextToken(FILE* file)
52{
53 ASSERT(file);
54 if (!file)
55 return String();
56
57 char buffer[maxBuffer] = {0, };
58 unsigned int index = 0;
59 while (index < maxBuffer) {
60 int ch = fgetc(file);
61 if (ch == EOF || (isASCIISpace(ch) && index)) // Break on non-initial ASCII space.
62 break;
63 if (!isASCIISpace(ch)) {
64 buffer[index] = ch;
65 index++;
66 }
67 }
68
69 return String(buffer);
70}
71
72static inline void appendKeyValuePair(WebMemoryStatistics& stats, const String& key, size_t value)
73{
74 stats.keys.append(key);
75 stats.values.append(value);
76}
77
78String WebMemorySampler::processName() const
79{
80 char processPath[maxProcessPath];
81 snprintf(processPath, maxProcessPath, "/proc/self/status");
82 FILE* statusFileDescriptor = fopen(processPath, "r");
83 if (!statusFileDescriptor)
84 return String();
85
86 nextToken(statusFileDescriptor);
87 String processName = nextToken(statusFileDescriptor);
88
89 fclose(statusFileDescriptor);
90
91 return processName;
92}
93
94WebMemoryStatistics WebMemorySampler::sampleWebKit() const
95{
96 WebMemoryStatistics webKitMemoryStats;
97
98 WallTime now = WallTime::now();
99
100 appendKeyValuePair(webKitMemoryStats, "Timestamp"_s, now.secondsSinceEpoch().seconds());
101
102 ProcessMemoryStatus processMemoryStatus;
103 currentProcessMemoryStatus(processMemoryStatus);
104
105 appendKeyValuePair(webKitMemoryStats, "Total Program Bytes"_s, processMemoryStatus.size);
106 appendKeyValuePair(webKitMemoryStats, "Resident Set Bytes"_s, processMemoryStatus.resident);
107 appendKeyValuePair(webKitMemoryStats, "Resident Shared Bytes"_s, processMemoryStatus.shared);
108 appendKeyValuePair(webKitMemoryStats, "Text Bytes"_s, processMemoryStatus.text);
109 appendKeyValuePair(webKitMemoryStats, "Library Bytes"_s, processMemoryStatus.lib);
110 appendKeyValuePair(webKitMemoryStats, "Data + Stack Bytes"_s, processMemoryStatus.data);
111 appendKeyValuePair(webKitMemoryStats, "Dirty Bytes"_s, processMemoryStatus.dt);
112
113 size_t totalBytesInUse = 0;
114 size_t totalBytesCommitted = 0;
115
116 auto fastMallocStatistics = WTF::fastMallocStatistics();
117 size_t fastMallocBytesInUse = fastMallocStatistics.committedVMBytes - fastMallocStatistics.freeListBytes;
118 size_t fastMallocBytesCommitted = fastMallocStatistics.committedVMBytes;
119 totalBytesInUse += fastMallocBytesInUse;
120 totalBytesCommitted += fastMallocBytesCommitted;
121
122 appendKeyValuePair(webKitMemoryStats, "Fast Malloc In Use"_s, fastMallocBytesInUse);
123 appendKeyValuePair(webKitMemoryStats, "Fast Malloc Committed Memory"_s, fastMallocBytesCommitted);
124
125 size_t jscHeapBytesInUse = commonVM().heap.size();
126 size_t jscHeapBytesCommitted = commonVM().heap.capacity();
127 totalBytesInUse += jscHeapBytesInUse;
128 totalBytesCommitted += jscHeapBytesCommitted;
129
130 GlobalMemoryStatistics globalMemoryStats = globalMemoryStatistics();
131 totalBytesInUse += globalMemoryStats.stackBytes + globalMemoryStats.JITBytes;
132 totalBytesCommitted += globalMemoryStats.stackBytes + globalMemoryStats.JITBytes;
133
134 appendKeyValuePair(webKitMemoryStats, "JavaScript Heap In Use"_s, jscHeapBytesInUse);
135 appendKeyValuePair(webKitMemoryStats, "JavaScript Heap Committed Memory"_s, jscHeapBytesCommitted);
136
137 appendKeyValuePair(webKitMemoryStats, "JavaScript Stack Bytes"_s, globalMemoryStats.stackBytes);
138 appendKeyValuePair(webKitMemoryStats, "JavaScript JIT Bytes"_s, globalMemoryStats.JITBytes);
139
140 appendKeyValuePair(webKitMemoryStats, "Total Memory In Use"_s, totalBytesInUse);
141 appendKeyValuePair(webKitMemoryStats, "Total Committed Memory"_s, totalBytesCommitted);
142
143 struct sysinfo systemInfo;
144 if (!sysinfo(&systemInfo)) {
145 appendKeyValuePair(webKitMemoryStats, "System Total Bytes"_s, systemInfo.totalram);
146 appendKeyValuePair(webKitMemoryStats, "Available Bytes"_s, systemInfo.freeram);
147 appendKeyValuePair(webKitMemoryStats, "Shared Bytes"_s, systemInfo.sharedram);
148 appendKeyValuePair(webKitMemoryStats, "Buffer Bytes"_s, systemInfo.bufferram);
149 appendKeyValuePair(webKitMemoryStats, "Total Swap Bytes"_s, systemInfo.totalswap);
150 appendKeyValuePair(webKitMemoryStats, "Available Swap Bytes"_s, systemInfo.freeswap);
151 }
152
153 return webKitMemoryStats;
154}
155
156void WebMemorySampler::sendMemoryPressureEvent()
157{
158 notImplemented();
159}
160
161}
162#endif
163