1/* 2 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 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'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY 17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 * 24 */ 25 26#import "config.h" 27#import "WebMemorySampler.h" 28 29#if ENABLE(MEMORY_SAMPLER) 30 31#import <JavaScriptCore/MemoryStatistics.h> 32#import <mach/mach.h> 33#import <mach/task.h> 34#import <mach/mach_types.h> 35#import <malloc/malloc.h> 36#import <notify.h> 37#import <runtime/JSLock.h> 38#import <WebCore/JSDOMWindow.h> 39#import <wtf/CurrentTime.h> 40 41using namespace WebCore; 42using namespace JSC; 43using namespace WTF; 44 45namespace WebKit { 46 47struct SystemMallocStats { 48 malloc_statistics_t defaultMallocZoneStats; 49 malloc_statistics_t dispatchContinuationMallocZoneStats; 50 malloc_statistics_t purgeableMallocZoneStats; 51}; 52 53SystemMallocStats WebMemorySampler::sampleSystemMalloc() const 54{ 55 static const char* defaultMallocZoneName = "DefaultMallocZone"; 56 static const char* dispatchContinuationMallocZoneName = "DispatchContinuations"; 57 static const char* purgeableMallocZoneName = "DefaultPurgeableMallocZone"; 58 SystemMallocStats mallocStats; 59 vm_address_t* zones; 60 unsigned count; 61 62 // Zero out the structures in case a zone is missing 63 malloc_statistics_t stats; 64 stats.blocks_in_use = 0; 65 stats.size_in_use = 0; 66 stats.max_size_in_use = 0; 67 stats.size_allocated = 0; 68 mallocStats.defaultMallocZoneStats = stats; 69 mallocStats.dispatchContinuationMallocZoneStats = stats; 70 mallocStats.purgeableMallocZoneStats = stats; 71 72 malloc_get_all_zones(mach_task_self(), 0, &zones, &count); 73 for (unsigned i = 0; i < count; i++) { 74 if (const char* name = malloc_get_zone_name(reinterpret_cast<malloc_zone_t*>(zones[i]))) { 75 stats.blocks_in_use = 0; 76 stats.size_in_use = 0; 77 stats.max_size_in_use = 0; 78 stats.size_allocated = 0; 79 malloc_zone_statistics(reinterpret_cast<malloc_zone_t*>(zones[i]), &stats); 80 if (!strcmp(name, defaultMallocZoneName)) 81 mallocStats.defaultMallocZoneStats = stats; 82 else if (!strcmp(name, dispatchContinuationMallocZoneName)) 83 mallocStats.dispatchContinuationMallocZoneStats = stats; 84 else if (!strcmp(name, purgeableMallocZoneName)) 85 mallocStats.purgeableMallocZoneStats = stats; 86 } 87 } 88 return mallocStats; 89} 90 91size_t WebMemorySampler::sampleProcessCommittedBytes() const 92{ 93 task_basic_info_64 taskInfo; 94 mach_msg_type_number_t count = TASK_BASIC_INFO_64_COUNT; 95 task_info(mach_task_self(), TASK_BASIC_INFO_64, reinterpret_cast<task_info_t>(&taskInfo), &count); 96 return taskInfo.resident_size; 97} 98 99String WebMemorySampler::processName() const 100{ 101 NSString *appName = [[NSBundle mainBundle] bundleIdentifier]; 102 if (!appName) 103 appName = [[NSProcessInfo processInfo] processName]; 104 return String(appName); 105} 106 107WebMemoryStatistics WebMemorySampler::sampleWebKit() const 108{ 109 size_t totalBytesInUse = 0, totalBytesCommitted = 0; 110 111 WebMemoryStatistics webKitMemoryStats; 112 113 FastMallocStatistics fastMallocStatistics = WTF::fastMallocStatistics(); 114 size_t fastMallocBytesInUse = fastMallocStatistics.committedVMBytes - fastMallocStatistics.freeListBytes; 115 size_t fastMallocBytesCommitted = fastMallocStatistics.committedVMBytes; 116 totalBytesInUse += fastMallocBytesInUse; 117 totalBytesCommitted += fastMallocBytesCommitted; 118 119 JSLockHolder lock(JSDOMWindow::commonVM()); 120 size_t jscHeapBytesInUse = JSDOMWindow::commonVM().heap.size(); 121 size_t jscHeapBytesCommitted = JSDOMWindow::commonVM().heap.capacity(); 122 totalBytesInUse += jscHeapBytesInUse; 123 totalBytesCommitted += jscHeapBytesCommitted; 124 125 GlobalMemoryStatistics globalMemoryStats = globalMemoryStatistics(); 126 totalBytesInUse += globalMemoryStats.stackBytes + globalMemoryStats.JITBytes; 127 totalBytesCommitted += globalMemoryStats.stackBytes + globalMemoryStats.JITBytes; 128 129 SystemMallocStats systemStats = sampleSystemMalloc(); 130 131 size_t defaultMallocZoneBytesInUse = systemStats.defaultMallocZoneStats.size_in_use; 132 size_t dispatchContinuationMallocZoneBytesInUse = systemStats.dispatchContinuationMallocZoneStats.size_in_use; 133 size_t purgeableMallocZoneBytesInUse = systemStats.purgeableMallocZoneStats.size_in_use; 134 size_t defaultMallocZoneBytesCommitted = systemStats.defaultMallocZoneStats.size_allocated; 135 size_t dispatchContinuationMallocZoneBytesCommitted = systemStats.dispatchContinuationMallocZoneStats.size_allocated; 136 size_t purgeableMallocZoneBytesCommitted = systemStats.purgeableMallocZoneStats.size_allocated; 137 totalBytesInUse += defaultMallocZoneBytesInUse + dispatchContinuationMallocZoneBytesInUse + purgeableMallocZoneBytesInUse; 138 totalBytesCommitted += defaultMallocZoneBytesCommitted + dispatchContinuationMallocZoneBytesCommitted + purgeableMallocZoneBytesCommitted; 139 140 size_t residentSize = sampleProcessCommittedBytes(); 141 142 double now = currentTime(); 143 144 webKitMemoryStats.keys.append(String("Timestamp")); 145 webKitMemoryStats.values.append(now); 146 webKitMemoryStats.keys.append(String("Total Bytes of Memory In Use")); 147 webKitMemoryStats.values.append(totalBytesInUse); 148 webKitMemoryStats.keys.append(String("Fast Malloc Zone Bytes")); 149 webKitMemoryStats.values.append(fastMallocBytesInUse); 150 webKitMemoryStats.keys.append(String("Default Malloc Zone Bytes")); 151 webKitMemoryStats.values.append(defaultMallocZoneBytesInUse); 152 webKitMemoryStats.keys.append(String("Dispatch Continuation Malloc Zone Bytes")); 153 webKitMemoryStats.values.append(dispatchContinuationMallocZoneBytesInUse); 154 webKitMemoryStats.keys.append(String("Purgeable Malloc Zone Bytes")); 155 webKitMemoryStats.values.append(purgeableMallocZoneBytesInUse); 156 webKitMemoryStats.keys.append(String("JavaScript Heap Bytes")); 157 webKitMemoryStats.values.append(jscHeapBytesInUse); 158 webKitMemoryStats.keys.append(String("Total Bytes of Committed Memory")); 159 webKitMemoryStats.values.append(totalBytesCommitted); 160 webKitMemoryStats.keys.append(String("Fast Malloc Zone Bytes")); 161 webKitMemoryStats.values.append(fastMallocBytesCommitted); 162 webKitMemoryStats.keys.append(String("Default Malloc Zone Bytes")); 163 webKitMemoryStats.values.append(defaultMallocZoneBytesCommitted); 164 webKitMemoryStats.keys.append(String("Dispatch Continuation Malloc Zone Bytes")); 165 webKitMemoryStats.values.append(dispatchContinuationMallocZoneBytesCommitted); 166 webKitMemoryStats.keys.append(String("Purgeable Malloc Zone Bytes")); 167 webKitMemoryStats.values.append(purgeableMallocZoneBytesCommitted); 168 webKitMemoryStats.keys.append(String("JavaScript Heap Bytes")); 169 webKitMemoryStats.values.append(jscHeapBytesCommitted); 170 webKitMemoryStats.keys.append(String("JavaScript Stack Bytes")); 171 webKitMemoryStats.values.append(globalMemoryStats.stackBytes); 172 webKitMemoryStats.keys.append(String("JavaScript JIT Bytes")); 173 webKitMemoryStats.values.append(globalMemoryStats.JITBytes); 174 webKitMemoryStats.keys.append(String("Resident Size")); 175 webKitMemoryStats.values.append(residentSize); 176 177 return webKitMemoryStats; 178} 179 180void WebMemorySampler::sendMemoryPressureEvent() 181{ 182 // Free memory that could be released if we needed more. 183 // We want to track memory that cannot. 184 notify_post("org.WebKit.lowMemory"); 185} 186 187} 188 189#endif 190 191