WebMemorySampler.mac.mm 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  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. #import "config.h"
  26. #import "WebMemorySampler.h"
  27. #if ENABLE(MEMORY_SAMPLER)
  28. #import <JavaScriptCore/MemoryStatistics.h>
  29. #import <mach/mach.h>
  30. #import <mach/task.h>
  31. #import <mach/mach_types.h>
  32. #import <malloc/malloc.h>
  33. #import <notify.h>
  34. #import <runtime/JSLock.h>
  35. #import <WebCore/JSDOMWindow.h>
  36. #import <wtf/CurrentTime.h>
  37. using namespace WebCore;
  38. using namespace JSC;
  39. using namespace WTF;
  40. namespace WebKit {
  41. struct SystemMallocStats {
  42. malloc_statistics_t defaultMallocZoneStats;
  43. malloc_statistics_t dispatchContinuationMallocZoneStats;
  44. malloc_statistics_t purgeableMallocZoneStats;
  45. };
  46. SystemMallocStats WebMemorySampler::sampleSystemMalloc() const
  47. {
  48. static const char* defaultMallocZoneName = "DefaultMallocZone";
  49. static const char* dispatchContinuationMallocZoneName = "DispatchContinuations";
  50. static const char* purgeableMallocZoneName = "DefaultPurgeableMallocZone";
  51. SystemMallocStats mallocStats;
  52. vm_address_t* zones;
  53. unsigned count;
  54. // Zero out the structures in case a zone is missing
  55. malloc_statistics_t stats;
  56. stats.blocks_in_use = 0;
  57. stats.size_in_use = 0;
  58. stats.max_size_in_use = 0;
  59. stats.size_allocated = 0;
  60. mallocStats.defaultMallocZoneStats = stats;
  61. mallocStats.dispatchContinuationMallocZoneStats = stats;
  62. mallocStats.purgeableMallocZoneStats = stats;
  63. malloc_get_all_zones(mach_task_self(), 0, &zones, &count);
  64. for (unsigned i = 0; i < count; i++) {
  65. if (const char* name = malloc_get_zone_name(reinterpret_cast<malloc_zone_t*>(zones[i]))) {
  66. stats.blocks_in_use = 0;
  67. stats.size_in_use = 0;
  68. stats.max_size_in_use = 0;
  69. stats.size_allocated = 0;
  70. malloc_zone_statistics(reinterpret_cast<malloc_zone_t*>(zones[i]), &stats);
  71. if (!strcmp(name, defaultMallocZoneName))
  72. mallocStats.defaultMallocZoneStats = stats;
  73. else if (!strcmp(name, dispatchContinuationMallocZoneName))
  74. mallocStats.dispatchContinuationMallocZoneStats = stats;
  75. else if (!strcmp(name, purgeableMallocZoneName))
  76. mallocStats.purgeableMallocZoneStats = stats;
  77. }
  78. }
  79. return mallocStats;
  80. }
  81. size_t WebMemorySampler::sampleProcessCommittedBytes() const
  82. {
  83. task_basic_info_64 taskInfo;
  84. mach_msg_type_number_t count = TASK_BASIC_INFO_64_COUNT;
  85. task_info(mach_task_self(), TASK_BASIC_INFO_64, reinterpret_cast<task_info_t>(&taskInfo), &count);
  86. return taskInfo.resident_size;
  87. }
  88. String WebMemorySampler::processName() const
  89. {
  90. NSString *appName = [[NSBundle mainBundle] bundleIdentifier];
  91. if (!appName)
  92. appName = [[NSProcessInfo processInfo] processName];
  93. return String(appName);
  94. }
  95. WebMemoryStatistics WebMemorySampler::sampleWebKit() const
  96. {
  97. size_t totalBytesInUse = 0, totalBytesCommitted = 0;
  98. WebMemoryStatistics webKitMemoryStats;
  99. FastMallocStatistics fastMallocStatistics = WTF::fastMallocStatistics();
  100. size_t fastMallocBytesInUse = fastMallocStatistics.committedVMBytes - fastMallocStatistics.freeListBytes;
  101. size_t fastMallocBytesCommitted = fastMallocStatistics.committedVMBytes;
  102. totalBytesInUse += fastMallocBytesInUse;
  103. totalBytesCommitted += fastMallocBytesCommitted;
  104. JSLockHolder lock(JSDOMWindow::commonVM());
  105. size_t jscHeapBytesInUse = JSDOMWindow::commonVM()->heap.size();
  106. size_t jscHeapBytesCommitted = JSDOMWindow::commonVM()->heap.capacity();
  107. totalBytesInUse += jscHeapBytesInUse;
  108. totalBytesCommitted += jscHeapBytesCommitted;
  109. GlobalMemoryStatistics globalMemoryStats = globalMemoryStatistics();
  110. totalBytesInUse += globalMemoryStats.stackBytes + globalMemoryStats.JITBytes;
  111. totalBytesCommitted += globalMemoryStats.stackBytes + globalMemoryStats.JITBytes;
  112. SystemMallocStats systemStats = sampleSystemMalloc();
  113. size_t defaultMallocZoneBytesInUse = systemStats.defaultMallocZoneStats.size_in_use;
  114. size_t dispatchContinuationMallocZoneBytesInUse = systemStats.dispatchContinuationMallocZoneStats.size_in_use;
  115. size_t purgeableMallocZoneBytesInUse = systemStats.purgeableMallocZoneStats.size_in_use;
  116. size_t defaultMallocZoneBytesCommitted = systemStats.defaultMallocZoneStats.size_allocated;
  117. size_t dispatchContinuationMallocZoneBytesCommitted = systemStats.dispatchContinuationMallocZoneStats.size_allocated;
  118. size_t purgeableMallocZoneBytesCommitted = systemStats.purgeableMallocZoneStats.size_allocated;
  119. totalBytesInUse += defaultMallocZoneBytesInUse + dispatchContinuationMallocZoneBytesInUse + purgeableMallocZoneBytesInUse;
  120. totalBytesCommitted += defaultMallocZoneBytesCommitted + dispatchContinuationMallocZoneBytesCommitted + purgeableMallocZoneBytesCommitted;
  121. size_t residentSize = sampleProcessCommittedBytes();
  122. double now = currentTime();
  123. webKitMemoryStats.keys.append(String("Timestamp"));
  124. webKitMemoryStats.values.append(now);
  125. webKitMemoryStats.keys.append(String("Total Bytes of Memory In Use"));
  126. webKitMemoryStats.values.append(totalBytesInUse);
  127. webKitMemoryStats.keys.append(String("Fast Malloc Zone Bytes"));
  128. webKitMemoryStats.values.append(fastMallocBytesInUse);
  129. webKitMemoryStats.keys.append(String("Default Malloc Zone Bytes"));
  130. webKitMemoryStats.values.append(defaultMallocZoneBytesInUse);
  131. webKitMemoryStats.keys.append(String("Dispatch Continuation Malloc Zone Bytes"));
  132. webKitMemoryStats.values.append(dispatchContinuationMallocZoneBytesInUse);
  133. webKitMemoryStats.keys.append(String("Purgeable Malloc Zone Bytes"));
  134. webKitMemoryStats.values.append(purgeableMallocZoneBytesInUse);
  135. webKitMemoryStats.keys.append(String("JavaScript Heap Bytes"));
  136. webKitMemoryStats.values.append(jscHeapBytesInUse);
  137. webKitMemoryStats.keys.append(String("Total Bytes of Committed Memory"));
  138. webKitMemoryStats.values.append(totalBytesCommitted);
  139. webKitMemoryStats.keys.append(String("Fast Malloc Zone Bytes"));
  140. webKitMemoryStats.values.append(fastMallocBytesCommitted);
  141. webKitMemoryStats.keys.append(String("Default Malloc Zone Bytes"));
  142. webKitMemoryStats.values.append(defaultMallocZoneBytesCommitted);
  143. webKitMemoryStats.keys.append(String("Dispatch Continuation Malloc Zone Bytes"));
  144. webKitMemoryStats.values.append(dispatchContinuationMallocZoneBytesCommitted);
  145. webKitMemoryStats.keys.append(String("Purgeable Malloc Zone Bytes"));
  146. webKitMemoryStats.values.append(purgeableMallocZoneBytesCommitted);
  147. webKitMemoryStats.keys.append(String("JavaScript Heap Bytes"));
  148. webKitMemoryStats.values.append(jscHeapBytesCommitted);
  149. webKitMemoryStats.keys.append(String("JavaScript Stack Bytes"));
  150. webKitMemoryStats.values.append(globalMemoryStats.stackBytes);
  151. webKitMemoryStats.keys.append(String("JavaScript JIT Bytes"));
  152. webKitMemoryStats.values.append(globalMemoryStats.JITBytes);
  153. webKitMemoryStats.keys.append(String("Resident Size"));
  154. webKitMemoryStats.values.append(residentSize);
  155. return webKitMemoryStats;
  156. }
  157. void WebMemorySampler::sendMemoryPressureEvent()
  158. {
  159. // Free memory that could be released if we needed more.
  160. // We want to track memory that cannot.
  161. notify_post("org.WebKit.lowMemory");
  162. }
  163. }
  164. #endif