Home | History | Annotate | Download | only in metrics
      1 # Copyright 2013 The Chromium Authors. All rights reserved.
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 import json
      6 import logging
      7 
      8 from metrics import Metric
      9 from telemetry.value import scalar
     10 
     11 
     12 _COUNTER_NAMES = [
     13     'V8.OsMemoryAllocated',
     14     'V8.MemoryNewSpaceBytesAvailable',
     15     'V8.MemoryNewSpaceBytesCommitted',
     16     'V8.MemoryNewSpaceBytesUsed',
     17     'V8.MemoryOldPointerSpaceBytesAvailable',
     18     'V8.MemoryOldPointerSpaceBytesCommitted',
     19     'V8.MemoryOldPointerSpaceBytesUsed',
     20     'V8.MemoryOldDataSpaceBytesAvailable',
     21     'V8.MemoryOldDataSpaceBytesCommitted',
     22     'V8.MemoryOldDataSpaceBytesUsed',
     23     'V8.MemoryCodeSpaceBytesAvailable',
     24     'V8.MemoryCodeSpaceBytesCommitted',
     25     'V8.MemoryCodeSpaceBytesUsed',
     26     'V8.MemoryMapSpaceBytesAvailable',
     27     'V8.MemoryMapSpaceBytesCommitted',
     28     'V8.MemoryMapSpaceBytesUsed',
     29     'V8.MemoryCellSpaceBytesAvailable',
     30     'V8.MemoryCellSpaceBytesCommitted',
     31     'V8.MemoryCellSpaceBytesUsed',
     32     'V8.MemoryPropertyCellSpaceBytesAvailable',
     33     'V8.MemoryPropertyCellSpaceBytesCommitted',
     34     'V8.MemoryPropertyCellSpaceBytesUsed',
     35     'V8.MemoryLoSpaceBytesAvailable',
     36     'V8.MemoryLoSpaceBytesCommitted',
     37     'V8.MemoryLoSpaceBytesUsed',
     38     'V8.SizeOf_ACCESSOR_PAIR_TYPE',
     39     'V8.SizeOf_ACCESS_CHECK_INFO_TYPE',
     40     'V8.SizeOf_ALIASED_ARGUMENTS_ENTRY_TYPE',
     41     'V8.SizeOf_ALLOCATION_MEMENTO_TYPE',
     42     'V8.SizeOf_ALLOCATION_SITE_TYPE',
     43     'V8.SizeOf_ASCII_INTERNALIZED_STRING_TYPE',
     44     'V8.SizeOf_ASCII_STRING_TYPE',
     45     'V8.SizeOf_BOX_TYPE',
     46     'V8.SizeOf_BREAK_POINT_INFO_TYPE',
     47     'V8.SizeOf_BYTE_ARRAY_TYPE',
     48     'V8.SizeOf_CALL_HANDLER_INFO_TYPE',
     49     'V8.SizeOf_CELL_TYPE',
     50     'V8.SizeOf_CODE_AGE-NotExecuted',
     51     'V8.SizeOf_CODE_AGE-ExecutedOnce',
     52     'V8.SizeOf_CODE_AGE-NoAge',
     53     'V8.SizeOf_CODE_AGE-Quadragenarian',
     54     'V8.SizeOf_CODE_AGE-Quinquagenarian',
     55     'V8.SizeOf_CODE_AGE-Sexagenarian',
     56     'V8.SizeOf_CODE_AGE-Septuagenarian',
     57     'V8.SizeOf_CODE_AGE-Octogenarian',
     58     'V8.SizeOf_CODE_CACHE_TYPE',
     59     'V8.SizeOf_CODE_TYPE',
     60     'V8.SizeOf_CODE_TYPE-BINARY_OP_IC',
     61     'V8.SizeOf_CODE_TYPE-BUILTIN',
     62     'V8.SizeOf_CODE_TYPE-CALL_IC',
     63     'V8.SizeOf_CODE_TYPE-COMPARE_IC',
     64     'V8.SizeOf_CODE_TYPE-COMPARE_NIL_IC',
     65     'V8.SizeOf_CODE_TYPE-FUNCTION',
     66     'V8.SizeOf_CODE_TYPE-KEYED_CALL_IC',
     67     'V8.SizeOf_CODE_TYPE-KEYED_LOAD_IC',
     68     'V8.SizeOf_CODE_TYPE-KEYED_STORE_IC',
     69     'V8.SizeOf_CODE_TYPE-LOAD_IC',
     70     'V8.SizeOf_CODE_TYPE-OPTIMIZED_FUNCTION',
     71     'V8.SizeOf_CODE_TYPE-REGEXP',
     72     'V8.SizeOf_CODE_TYPE-STORE_IC',
     73     'V8.SizeOf_CODE_TYPE-STUB',
     74     'V8.SizeOf_CODE_TYPE-TO_BOOLEAN_IC',
     75     'V8.SizeOf_CONS_ASCII_INTERNALIZED_STRING_TYPE',
     76     'V8.SizeOf_CONS_ASCII_STRING_TYPE',
     77     'V8.SizeOf_CONS_INTERNALIZED_STRING_TYPE',
     78     'V8.SizeOf_CONS_STRING_TYPE',
     79     'V8.SizeOf_DEBUG_INFO_TYPE',
     80     'V8.SizeOf_DECLARED_ACCESSOR_DESCRIPTOR_TYPE',
     81     'V8.SizeOf_DECLARED_ACCESSOR_INFO_TYPE',
     82     'V8.SizeOf_EXECUTABLE_ACCESSOR_INFO_TYPE',
     83     'V8.SizeOf_EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE',
     84     'V8.SizeOf_EXTERNAL_ASCII_STRING_TYPE',
     85     'V8.SizeOf_EXTERNAL_BYTE_ARRAY_TYPE',
     86     'V8.SizeOf_EXTERNAL_DOUBLE_ARRAY_TYPE',
     87     'V8.SizeOf_EXTERNAL_FLOAT_ARRAY_TYPE',
     88     'V8.SizeOf_EXTERNAL_INTERNALIZED_STRING_TYPE',
     89     'V8.SizeOf_EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE',
     90     'V8.SizeOf_EXTERNAL_INT_ARRAY_TYPE',
     91     'V8.SizeOf_EXTERNAL_PIXEL_ARRAY_TYPE',
     92     'V8.SizeOf_EXTERNAL_SHORT_ARRAY_TYPE',
     93     'V8.SizeOf_EXTERNAL_STRING_TYPE',
     94     'V8.SizeOf_EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE',
     95     'V8.SizeOf_EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE',
     96     'V8.SizeOf_EXTERNAL_UNSIGNED_INT_ARRAY_TYPE',
     97     'V8.SizeOf_EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE',
     98     'V8.SizeOf_FILLER_TYPE',
     99     'V8.SizeOf_FIXED_ARRAY-DESCRIPTOR_ARRAY_SUB_TYPE',
    100     'V8.SizeOf_FIXED_ARRAY-DICTIONARY_ELEMENTS_SUB_TYPE',
    101     'V8.SizeOf_FIXED_ARRAY-DICTIONARY_PROPERTIES_SUB_TYPE',
    102     'V8.SizeOf_FIXED_ARRAY-FAST_ELEMENTS_SUB_TYPE',
    103     'V8.SizeOf_FIXED_ARRAY-FAST_PROPERTIES_SUB_TYPE',
    104     'V8.SizeOf_FIXED_ARRAY-MAP_CODE_CACHE_SUB_TYPE',
    105     'V8.SizeOf_FIXED_ARRAY-SCOPE_INFO_SUB_TYPE',
    106     'V8.SizeOf_FIXED_ARRAY-STRING_TABLE_SUB_TYPE',
    107     'V8.SizeOf_FIXED_ARRAY-TRANSITION_ARRAY_SUB_TYPE',
    108     'V8.SizeOf_FIXED_ARRAY_TYPE',
    109     'V8.SizeOf_FIXED_DOUBLE_ARRAY_TYPE',
    110     'V8.SizeOf_FOREIGN_TYPE',
    111     'V8.SizeOf_FREE_SPACE_TYPE',
    112     'V8.SizeOf_FUNCTION_TEMPLATE_INFO_TYPE',
    113     'V8.SizeOf_HEAP_NUMBER_TYPE',
    114     'V8.SizeOf_INTERCEPTOR_INFO_TYPE',
    115     'V8.SizeOf_INTERNALIZED_STRING_TYPE',
    116     'V8.SizeOf_JS_ARRAY_BUFFER_TYPE',
    117     'V8.SizeOf_JS_ARRAY_TYPE',
    118     'V8.SizeOf_JS_BUILTINS_OBJECT_TYPE',
    119     'V8.SizeOf_JS_CONTEXT_EXTENSION_OBJECT_TYPE',
    120     'V8.SizeOf_JS_DATA_VIEW_TYPE',
    121     'V8.SizeOf_JS_DATE_TYPE',
    122     'V8.SizeOf_JS_FUNCTION_PROXY_TYPE',
    123     'V8.SizeOf_JS_FUNCTION_TYPE',
    124     'V8.SizeOf_JS_GENERATOR_OBJECT_TYPE',
    125     'V8.SizeOf_JS_GLOBAL_OBJECT_TYPE',
    126     'V8.SizeOf_JS_GLOBAL_PROXY_TYPE',
    127     'V8.SizeOf_JS_MAP_TYPE',
    128     'V8.SizeOf_JS_MESSAGE_OBJECT_TYPE',
    129     'V8.SizeOf_JS_MODULE_TYPE',
    130     'V8.SizeOf_JS_OBJECT_TYPE',
    131     'V8.SizeOf_JS_PROXY_TYPE',
    132     'V8.SizeOf_JS_REGEXP_TYPE',
    133     'V8.SizeOf_JS_SET_TYPE',
    134     'V8.SizeOf_JS_TYPED_ARRAY_TYPE',
    135     'V8.SizeOf_JS_VALUE_TYPE',
    136     'V8.SizeOf_JS_WEAK_MAP_TYPE',
    137     'V8.SizeOf_JS_WEAK_SET_TYPE',
    138     'V8.SizeOf_MAP_TYPE',
    139     'V8.SizeOf_OBJECT_TEMPLATE_INFO_TYPE',
    140     'V8.SizeOf_ODDBALL_TYPE',
    141     'V8.SizeOf_POLYMORPHIC_CODE_CACHE_TYPE',
    142     'V8.SizeOf_PROPERTY_CELL_TYPE',
    143     'V8.SizeOf_SCRIPT_TYPE',
    144     'V8.SizeOf_SHARED_FUNCTION_INFO_TYPE',
    145     'V8.SizeOf_SHORT_EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE',
    146     'V8.SizeOf_SHORT_EXTERNAL_ASCII_STRING_TYPE',
    147     'V8.SizeOf_SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE',
    148     'V8.SizeOf_SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE',
    149     'V8.SizeOf_SHORT_EXTERNAL_STRING_TYPE',
    150     'V8.SizeOf_SHORT_EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE',
    151     'V8.SizeOf_SIGNATURE_INFO_TYPE',
    152     'V8.SizeOf_SLICED_ASCII_STRING_TYPE',
    153     'V8.SizeOf_SLICED_STRING_TYPE',
    154     'V8.SizeOf_STRING_TYPE',
    155     'V8.SizeOf_SYMBOL_TYPE',
    156     'V8.SizeOf_TYPE_FEEDBACK_INFO_TYPE',
    157     'V8.SizeOf_TYPE_SWITCH_INFO_TYPE',
    158 ]
    159 
    160 # Descriptions for what different counter names represent.
    161 DESCRIPTIONS = {
    162     'V8.MemoryExternalFragmentationTotal':
    163         'Total external memory fragmentation after each GC in percent.',
    164     'V8.MemoryHeapSampleTotalCommitted':
    165         'The total size of committed memory used by V8 after each GC in KB.',
    166     'V8.MemoryHeapSampleTotalUsed':
    167         'The total size of live memory used by V8 after each GC in KB.',
    168 }
    169 
    170 
    171 class V8ObjectStatsMetric(Metric):
    172   """V8ObjectStatsMetric gathers statistics on the size of types in the V8 heap.
    173 
    174   It does this by enabling the --track_gc_object_stats flag on V8 and reading
    175   these statistics from the StatsTableMetric.
    176   """
    177 
    178   def __init__(self, counters=None):
    179     super(V8ObjectStatsMetric, self).__init__()
    180     self._results = None
    181     self._counters = counters or _COUNTER_NAMES
    182 
    183   @classmethod
    184   def CustomizeBrowserOptions(cls, options):
    185     options.AppendExtraBrowserArgs([
    186         '--enable-stats-table',
    187         '--enable-benchmarking',
    188         '--js-flags=--track_gc_object_stats --expose_gc',
    189         # TODO(rmcilroy): This is needed for --enable-stats-table.  Update once
    190         # https://codereview.chromium.org/22911027/ lands.
    191         '--no-sandbox'
    192     ])
    193 
    194   @staticmethod
    195   def GetV8StatsTable(tab, counters):
    196 
    197     return tab.EvaluateJavaScript("""
    198         (function(counters) {
    199           var results = {};
    200           if (!window.chrome || !window.chrome.benchmarking)
    201             return results;
    202           try {
    203             window.gc();  // Trigger GC to ensure stats are checkpointed.
    204           } catch(e) {
    205             // window.gc() could have been mapped to something else,
    206             // just continue.
    207           }
    208           for (var i = 0; i < counters.length; i++)
    209             results[counters[i]] =
    210                 chrome.benchmarking.counterForRenderer(counters[i]);
    211           return results;
    212         })(%s);
    213         """ % json.dumps(counters))
    214 
    215   def Start(self, page, tab):
    216     """Do Nothing."""
    217     pass
    218 
    219   def Stop(self, page, tab):
    220     """Get the values in the stats table after the page is loaded."""
    221     self._results = V8ObjectStatsMetric.GetV8StatsTable(tab, self._counters)
    222     if not self._results:
    223       logging.warning('No V8 object stats from website: ' + page.display_name)
    224 
    225   def AddResults(self, tab, results):
    226     """Add results for this page to the results object."""
    227     assert self._results != None, 'Must call Stop() first'
    228     for counter_name in self._results:
    229       description = DESCRIPTIONS.get(counter_name)
    230       display_name = counter_name.replace('.', '_')
    231       results.AddValue(scalar.ScalarValue(
    232           results.current_page, display_name, 'kb',
    233           self._results[counter_name] / 1024.0, description=description))
    234