1 # Copyright 2014 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 telemetry
.core
.platform
import tracing_category_filter
8 from telemetry
.core
.platform
import tracing_options
9 from telemetry
.page
import action_runner
10 from telemetry
.page
import page_test
11 from telemetry
.results
import results_options
12 from telemetry
.timeline
.model
import TimelineModel
13 from telemetry
.util
import statistics
14 from telemetry
.value
import list_of_scalar_values
15 from telemetry
.value
import scalar
16 from telemetry
.value
import trace
19 _CR_RENDERER_MAIN
= 'CrRendererMain'
20 _RUN_SMOOTH_ACTIONS
= 'RunSmoothAllActions'
23 def _AddTracingResults(thread
, results
):
24 _GC_REASONS
= ['precise', 'conservative', 'idle', 'forced']
25 _GC_STAGES
= ['mark', 'lazy_sweep', 'complete_sweep']
27 def GetGcReason(event
, async_slices
):
34 return 'precise' if args
['precise'] else 'conservative'
36 if args
['gcReason'] == 'ConservativeGC':
38 if args
['gcReason'] == 'PreciseGC':
40 if args
['gcReason'] == 'ForcedGCForTesting':
41 for s
in async_slices
:
42 if s
.start
<= event
.start
and event
.end
<= s
.end
:
44 # Ignore this forced GC being out of target ranges
46 if args
['gcReason'] == 'IdleGC':
50 def DumpMetric(page
, name
, values
, unit
, results
):
52 results
.AddValue(list_of_scalar_values
.ListOfScalarValues(
53 page
, name
, unit
, values
[name
]))
54 results
.AddValue(scalar
.ScalarValue(
55 page
, name
+ '_max', unit
, max(values
[name
])))
56 results
.AddValue(scalar
.ScalarValue(
57 page
, name
+ '_total', unit
, sum(values
[name
])))
59 events
= thread
.all_slices
60 async_slices
= [s
for s
in thread
.async_slices
61 if s
.name
== 'BlinkGCTimeMeasurement']
64 values
= {'oilpan_coalesce': []}
65 for reason
in _GC_REASONS
:
66 for stage
in _GC_STAGES
:
67 values
['oilpan_%s_%s' % (reason
, stage
)] = []
73 complete_sweep_time
= 0
75 duration
= event
.thread_duration
or event
.duration
76 if event
.name
== 'ThreadHeap::coalesce':
77 values
['oilpan_coalesce'].append(duration
)
79 if event
.name
== 'Heap::collectGarbage':
80 if reason
is not None:
81 values
['oilpan_%s_mark' % reason
].append(mark_time
)
82 values
['oilpan_%s_lazy_sweep' % reason
].append(lazy_sweep_time
)
83 values
['oilpan_%s_complete_sweep' % reason
].append(complete_sweep_time
)
85 reason
= GetGcReason(event
, async_slices
)
88 complete_sweep_time
= 0
90 if event
.name
== 'ThreadHeap::lazySweepPages':
91 lazy_sweep_time
+= duration
93 if event
.name
== 'ThreadState::completeSweep':
94 complete_sweep_time
+= duration
97 if reason
is not None:
98 values
['oilpan_%s_mark' % reason
].append(mark_time
)
99 values
['oilpan_%s_lazy_sweep' % reason
].append(lazy_sweep_time
)
100 values
['oilpan_%s_complete_sweep' % reason
].append(complete_sweep_time
)
102 page
= results
.current_page
106 DumpMetric(page
, 'oilpan_coalesce', values
, unit
, results
)
107 for reason
in _GC_REASONS
:
108 for stage
in _GC_STAGES
:
109 DumpMetric(page
, 'oilpan_%s_%s' % (reason
, stage
), values
, unit
, results
)
111 # Summarize each stage
112 for stage
in _GC_STAGES
:
114 for reason
in _GC_REASONS
:
115 total_time
+= sum(values
['oilpan_%s_%s' % (reason
, stage
)])
117 scalar
.ScalarValue(page
, 'oilpan_%s' % stage
, unit
, total_time
))
119 # Summarize sweeping time
121 for stage
in ['lazy_sweep', 'complete_sweep']:
123 for reason
in _GC_REASONS
:
124 sweep_time
+= sum(values
['oilpan_%s_%s' % (reason
, stage
)])
125 key
= 'oilpan_%s' % stage
126 results
.AddValue(scalar
.ScalarValue(page
, key
, unit
, sweep_time
))
127 total_sweep_time
+= sweep_time
129 scalar
.ScalarValue(page
, 'oilpan_sweep', unit
, total_sweep_time
))
133 gc_time
+= sum(values
[key
])
134 results
.AddValue(scalar
.ScalarValue(page
, 'oilpan_gc', unit
, gc_time
))
137 class _OilpanGCTimesBase(page_test
.PageTest
):
138 def __init__(self
, action_name
=''):
139 super(_OilpanGCTimesBase
, self
).__init
__(action_name
)
140 self
._timeline
_model
= None
142 def WillNavigateToPage(self
, page
, tab
):
143 # FIXME: Remove webkit.console when blink.console lands in chromium and
144 # the ref builds are updated. crbug.com/386847
145 categories
= ['webkit.console', 'blink.console', 'blink_gc']
146 category_filter
= tracing_category_filter
.TracingCategoryFilter()
148 category_filter
.AddIncludedCategory(c
)
149 options
= tracing_options
.TracingOptions()
150 options
.enable_chrome_trace
= True
151 tab
.browser
.platform
.tracing_controller
.Start(options
, category_filter
,
154 def DidRunActions(self
, page
, tab
):
155 timeline_data
= tab
.browser
.platform
.tracing_controller
.Stop()
156 self
._timeline
_model
= TimelineModel(timeline_data
)
158 def ValidateAndMeasurePage(self
, page
, tab
, results
):
159 threads
= self
._timeline
_model
.GetAllThreads()
160 for thread
in threads
:
161 if thread
.name
== _CR_RENDERER_MAIN
:
162 _AddTracingResults(thread
, results
)
164 def CleanUpAfterPage(self
, page
, tab
):
165 if tab
.browser
.platform
.tracing_controller
.is_tracing_running
:
166 tab
.browser
.platform
.tracing_controller
.Stop()
169 class OilpanGCTimesForSmoothness(_OilpanGCTimesBase
):
171 super(OilpanGCTimesForSmoothness
, self
).__init
__()
172 self
._interaction
= None
174 def WillRunActions(self
, page
, tab
):
175 runner
= action_runner
.ActionRunner(tab
)
176 self
._interaction
= runner
.CreateInteraction(_RUN_SMOOTH_ACTIONS
)
177 self
._interaction
.Begin()
179 def DidRunActions(self
, page
, tab
):
180 self
._interaction
.End()
181 super(OilpanGCTimesForSmoothness
, self
).DidRunActions(page
, tab
)
184 class OilpanGCTimesForBlinkPerf(_OilpanGCTimesBase
):
186 super(OilpanGCTimesForBlinkPerf
, self
).__init
__()
187 with
open(os
.path
.join(os
.path
.dirname(__file__
), '..', 'benchmarks',
188 'blink_perf.js'), 'r') as f
:
189 self
._blink
_perf
_js
= f
.read()
191 def WillNavigateToPage(self
, page
, tab
):
192 page
.script_to_evaluate_on_commit
= self
._blink
_perf
_js
193 super(OilpanGCTimesForBlinkPerf
, self
).WillNavigateToPage(page
, tab
)
195 def DidRunActions(self
, page
, tab
):
196 tab
.WaitForJavaScriptExpression('testRunner.isDone', 600)
197 super(OilpanGCTimesForBlinkPerf
, self
).DidRunActions(page
, tab
)
200 class OilpanGCTimesForInternals(OilpanGCTimesForBlinkPerf
):
202 super(OilpanGCTimesForInternals
, self
).__init
__()
205 def CustomizeBrowserOptions(cls
, options
):
206 # 'expose-internals-for-testing' can be enabled on content shell.
207 assert 'content-shell' in options
.browser_type
208 options
.AppendExtraBrowserArgs(['--expose-internals-for-testing',
209 '--js-flags=--expose-gc'])