2 * Copyright (C) 2010 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include "MemoryInfo.h"
35 #include "ScriptGCEvent.h"
38 #include <wtf/CurrentTime.h>
39 #include <wtf/MainThread.h>
46 WTF_MAKE_NONCOPYABLE(HeapSizeCache);
53 void getCachedHeapSize(HeapInfo& info)
62 // We rate-limit queries to once every twenty minutes to make it more difficult
63 // for attackers to compare memory usage before and after some event.
64 const double TwentyMinutesInSeconds = 20 * 60;
66 double now = monotonicallyIncreasingTime();
67 if (now - m_lastUpdateTime >= TwentyMinutesInSeconds) {
69 m_lastUpdateTime = now;
75 ScriptGCEvent::getHeapSize(m_info);
76 m_info.usedJSHeapSize = quantizeMemorySize(m_info.usedJSHeapSize);
77 m_info.totalJSHeapSize = quantizeMemorySize(m_info.totalJSHeapSize);
78 m_info.jsHeapSizeLimit = quantizeMemorySize(m_info.jsHeapSizeLimit);
81 double m_lastUpdateTime;
86 // We quantize the sizes to make it more difficult for an attacker to see precise
87 // impact of operations on memory. The values are used for performance tuning,
88 // and hence don't need to be as refined when the value is large, so we threshold
89 // at a list of exponentially separated buckets.
90 size_t quantizeMemorySize(size_t size)
92 const int numberOfBuckets = 100;
93 DEFINE_STATIC_LOCAL(Vector<size_t>, bucketSizeList, ());
95 ASSERT(isMainThread());
96 if (bucketSizeList.isEmpty()) {
97 bucketSizeList.resize(numberOfBuckets);
99 float sizeOfNextBucket = 10000000.0; // First bucket size is roughly 10M.
100 const float largestBucketSize = 4000000000.0; // Roughly 4GB.
101 // We scale with the Nth root of the ratio, so that we use all the bucktes.
102 const float scalingFactor = exp(log(largestBucketSize / sizeOfNextBucket) / numberOfBuckets);
104 size_t nextPowerOfTen = static_cast<size_t>(pow(10, floor(log10(sizeOfNextBucket)) + 1) + 0.5);
105 size_t granularity = nextPowerOfTen / 1000; // We want 3 signficant digits.
107 for (int i = 0; i < numberOfBuckets; ++i) {
108 size_t currentBucketSize = static_cast<size_t>(sizeOfNextBucket);
109 bucketSizeList[i] = currentBucketSize - (currentBucketSize % granularity);
111 sizeOfNextBucket *= scalingFactor;
112 if (sizeOfNextBucket >= nextPowerOfTen) {
113 if (std::numeric_limits<size_t>::max() / 10 <= nextPowerOfTen)
114 nextPowerOfTen = std::numeric_limits<size_t>::max();
116 nextPowerOfTen *= 10;
121 // Watch out for overflow, if the range is too large for size_t.
122 if (i > 0 && bucketSizeList[i] < bucketSizeList[i - 1])
123 bucketSizeList[i] = std::numeric_limits<size_t>::max();
127 for (int i = 0; i < numberOfBuckets; ++i) {
128 if (size <= bucketSizeList[i])
129 return bucketSizeList[i];
132 return bucketSizeList[numberOfBuckets - 1];
137 MemoryInfo::MemoryInfo(Frame* frame)
139 if (!frame || !frame->settings())
142 #if ENABLE(INSPECTOR)
143 if (frame->settings()->memoryInfoEnabled())
144 ScriptGCEvent::getHeapSize(m_info);
145 else if (true || frame->settings()->quantizedMemoryInfoEnabled()) {
146 DEFINE_STATIC_LOCAL(HeapSizeCache, heapSizeCache, ());
147 heapSizeCache.getCachedHeapSize(m_info);
152 } // namespace WebCore