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.
7 from metrics
import histogram_util
8 from metrics
import Metric
11 {'name': 'V8.MemoryExternalFragmentationTotal', 'units': 'percent',
12 'type': histogram_util
.RENDERER_HISTOGRAM
},
13 {'name': 'V8.MemoryHeapSampleTotalCommitted', 'units': 'kb',
14 'type': histogram_util
.RENDERER_HISTOGRAM
},
15 {'name': 'V8.MemoryHeapSampleTotalUsed', 'units': 'kb',
16 'type': histogram_util
.RENDERER_HISTOGRAM
},
17 {'name': 'Memory.RendererUsed', 'units': 'kb',
18 'type': histogram_util
.RENDERER_HISTOGRAM
},
19 {'name': 'Memory.BrowserUsed', 'units': 'kb',
20 'type': histogram_util
.BROWSER_HISTOGRAM
}]
22 class MemoryMetric(Metric
):
23 """MemoryMetric gathers memory statistics from the browser object.
25 This includes both per-page histogram stats, most about javascript
26 memory usage, and overall memory stats from the system for the whole
29 def __init__(self
, browser
):
30 super(MemoryMetric
, self
).__init
__()
31 self
._browser
= browser
32 self
._start
_commit
_charge
= self
._browser
.memory_stats
['SystemCommitCharge']
33 self
._memory
_stats
= None
34 self
._histogram
_start
= dict()
35 self
._histogram
_delta
= dict()
38 def CustomizeBrowserOptions(cls
, options
):
39 options
.AppendExtraBrowserArgs([
40 '--enable-stats-collection-bindings',
41 '--enable-memory-benchmarking',
42 # For a hard-coded set of Google pages (such as GMail), we produce
43 # custom memory histograms (V8.Something_gmail) instead of the generic
44 # histograms (V8.Something), if we detect that a renderer is only
45 # rendering this page and no other pages. For this test, we need to
46 # disable histogram customizing, so that we get the same generic
47 # histograms produced for all pages.
48 '--disable-histogram-customizer'
51 def Start(self
, page
, tab
):
52 """Start the per-page preparation for this metric.
54 Here, this consists of recording the start value of all the histograms.
57 histogram_data
= histogram_util
.GetHistogram(
58 h
['type'], h
['name'], tab
)
59 # Histogram data may not be available
60 if not histogram_data
:
62 self
._histogram
_start
[h
['name']] = histogram_data
64 def Stop(self
, page
, tab
):
65 """Prepare the results for this page.
67 The results are the differences between the current histogram values
68 and the values when Start() was called.
70 assert self
._histogram
_start
, 'Must call Start() first'
72 # Histogram data may not be available
73 if h
['name'] not in self
._histogram
_start
:
75 histogram_data
= histogram_util
.GetHistogram(
76 h
['type'], h
['name'], tab
)
77 self
._histogram
_delta
[h
['name']] = histogram_util
.SubtractHistogram(
78 histogram_data
, self
._histogram
_start
[h
['name']])
80 def AddResults(self
, tab
, results
):
81 """Add results for this page to the results object."""
82 assert self
._histogram
_delta
, 'Must call Stop() first'
84 # Histogram data may not be available
85 if h
['name'] not in self
._histogram
_start
:
87 results
.Add(h
['name'], h
['units'], self
._histogram
_delta
[h
['name']],
88 data_type
='unimportant-histogram')
90 def AddSummaryResults(self
, results
, trace_name
=None):
91 """Add summary (overall) results to the results object."""
92 self
._memory
_stats
= self
._browser
.memory_stats
93 if not self
._memory
_stats
['Browser']:
96 metric
= 'resident_set_size'
97 if sys
.platform
== 'win32':
98 metric
= 'working_set'
100 def AddSummariesForProcessTypes(process_types_memory
, process_type_trace
):
101 """Add all summaries to the results for a given set of process types.
104 process_types_memory: A list of process types, e.g. Browser, 'Renderer'
105 process_type_trace: The name of this set of process types in the output
107 def AddSummary(value_name_memory
, value_name_trace
):
108 """Add a summary to the results for a given statistic.
111 value_name_memory: Name of some statistic, e.g. VM, WorkingSetSize
112 value_name_trace: Name of this statistic to be used in the output
114 if len(process_types_memory
) > 1 and value_name_memory
.endswith('Peak'):
117 for process_type_memory
in process_types_memory
:
118 stats
= self
._memory
_stats
[process_type_memory
]
119 if value_name_memory
in stats
:
120 values
.append(stats
[value_name_memory
])
123 current_trace
= '%s_%s' % (trace_name
, process_type_trace
)
124 chart_name
= value_name_trace
126 current_trace
= '%s_%s' % (value_name_trace
, process_type_trace
)
127 chart_name
= current_trace
128 results
.AddSummary(current_trace
, 'bytes', sum(values
),
129 chart_name
=chart_name
, data_type
='unimportant')
131 AddSummary('VM', 'vm_final_size')
132 AddSummary('WorkingSetSize', 'vm_%s_final_size' % metric
)
133 AddSummary('PrivateDirty', 'vm_private_dirty_final')
134 AddSummary('ProportionalSetSize', 'vm_proportional_set_size_final')
135 AddSummary('SharedDirty', 'vm_shared_dirty_final')
136 AddSummary('VMPeak', 'vm_peak_size')
137 AddSummary('WorkingSetSizePeak', '%s_peak_size' % metric
)
139 AddSummariesForProcessTypes(['Browser'], 'browser')
140 AddSummariesForProcessTypes(['Renderer'], 'renderer')
141 AddSummariesForProcessTypes(['Gpu'], 'gpu')
142 AddSummariesForProcessTypes(['Browser', 'Renderer', 'Gpu'], 'total')
144 end_commit_charge
= self
._memory
_stats
['SystemCommitCharge']
145 commit_charge_difference
= end_commit_charge
- self
._start
_commit
_charge
146 results
.AddSummary(trace_name
or 'commit_charge', 'kb',
147 commit_charge_difference
,
148 chart_name
='commit_charge',
149 data_type
='unimportant')
150 results
.AddSummary(trace_name
or 'processes', 'count',
151 self
._memory
_stats
['ProcessCount'],
152 chart_name
='processes',
153 data_type
='unimportant')