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