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
.page
import action_runner
8 from telemetry
.page
import page_test
9 from telemetry
.timeline
.model
import TimelineModel
10 from telemetry
.timeline
import tracing_category_filter
11 from telemetry
.timeline
import tracing_options
12 from telemetry
.value
import list_of_scalar_values
13 from telemetry
.value
import scalar
16 _CR_RENDERER_MAIN
= 'CrRendererMain'
17 _RUN_SMOOTH_ACTIONS
= 'RunSmoothAllActions'
20 def _AddTracingResults(thread
, results
):
21 _GC_REASONS
= ['precise', 'conservative', 'idle', 'forced']
22 _GC_STAGES
= ['mark', 'lazy_sweep', 'complete_sweep']
24 def GetGcReason(event
, async_slices
):
31 return 'precise' if args
['precise'] else 'conservative'
33 if args
['gcReason'] == 'ConservativeGC':
35 if args
['gcReason'] == 'PreciseGC':
37 if args
['gcReason'] == 'ForcedGCForTesting':
38 for s
in async_slices
:
39 if s
.start
<= event
.start
and event
.end
<= s
.end
:
41 # Ignore this forced GC being out of target ranges
43 if args
['gcReason'] == 'IdleGC':
47 def DumpMetric(page
, name
, values
, unit
, results
):
49 results
.AddValue(list_of_scalar_values
.ListOfScalarValues(
50 page
, name
, unit
, values
[name
]))
51 results
.AddValue(scalar
.ScalarValue(
52 page
, name
+ '_max', unit
, max(values
[name
])))
53 results
.AddValue(scalar
.ScalarValue(
54 page
, name
+ '_total', unit
, sum(values
[name
])))
56 events
= thread
.all_slices
57 async_slices
= [s
for s
in thread
.async_slices
58 if s
.name
== 'BlinkGCTimeMeasurement']
61 values
= {'oilpan_coalesce': []}
62 for reason
in _GC_REASONS
:
63 for stage
in _GC_STAGES
:
64 values
['oilpan_%s_%s' % (reason
, stage
)] = []
70 complete_sweep_time
= 0
72 duration
= event
.thread_duration
or event
.duration
73 if event
.name
== 'ThreadHeap::coalesce':
74 values
['oilpan_coalesce'].append(duration
)
76 if event
.name
== 'Heap::collectGarbage':
77 if reason
is not None:
78 values
['oilpan_%s_mark' % reason
].append(mark_time
)
79 values
['oilpan_%s_lazy_sweep' % reason
].append(lazy_sweep_time
)
80 values
['oilpan_%s_complete_sweep' % reason
].append(complete_sweep_time
)
82 reason
= GetGcReason(event
, async_slices
)
85 complete_sweep_time
= 0
87 if event
.name
== 'ThreadHeap::lazySweepPages':
88 lazy_sweep_time
+= duration
90 if event
.name
== 'ThreadState::completeSweep':
91 complete_sweep_time
+= duration
94 if reason
is not None:
95 values
['oilpan_%s_mark' % reason
].append(mark_time
)
96 values
['oilpan_%s_lazy_sweep' % reason
].append(lazy_sweep_time
)
97 values
['oilpan_%s_complete_sweep' % reason
].append(complete_sweep_time
)
99 page
= results
.current_page
103 DumpMetric(page
, 'oilpan_coalesce', values
, unit
, results
)
104 for reason
in _GC_REASONS
:
105 for stage
in _GC_STAGES
:
106 DumpMetric(page
, 'oilpan_%s_%s' % (reason
, stage
), values
, unit
, results
)
108 # Summarize each stage
109 for stage
in _GC_STAGES
:
111 for reason
in _GC_REASONS
:
112 total_time
+= sum(values
['oilpan_%s_%s' % (reason
, stage
)])
114 scalar
.ScalarValue(page
, 'oilpan_%s' % stage
, unit
, total_time
))
116 # Summarize sweeping time
118 for stage
in ['lazy_sweep', 'complete_sweep']:
120 for reason
in _GC_REASONS
:
121 sweep_time
+= sum(values
['oilpan_%s_%s' % (reason
, stage
)])
122 key
= 'oilpan_%s' % stage
123 results
.AddValue(scalar
.ScalarValue(page
, key
, unit
, sweep_time
))
124 total_sweep_time
+= sweep_time
126 scalar
.ScalarValue(page
, 'oilpan_sweep', unit
, total_sweep_time
))
130 gc_time
+= sum(values
[key
])
131 results
.AddValue(scalar
.ScalarValue(page
, 'oilpan_gc', unit
, gc_time
))
134 class _OilpanGCTimesBase(page_test
.PageTest
):
135 def __init__(self
, action_name
=''):
136 super(_OilpanGCTimesBase
, self
).__init
__(action_name
)
138 def WillNavigateToPage(self
, page
, tab
):
139 # FIXME: Remove webkit.console when blink.console lands in chromium and
140 # the ref builds are updated. crbug.com/386847
141 categories
= ['webkit.console', 'blink.console', 'blink_gc']
142 category_filter
= tracing_category_filter
.TracingCategoryFilter()
144 category_filter
.AddIncludedCategory(c
)
145 options
= tracing_options
.TracingOptions()
146 options
.enable_chrome_trace
= True
147 tab
.browser
.platform
.tracing_controller
.Start(options
, category_filter
,
150 def ValidateAndMeasurePage(self
, page
, tab
, results
):
151 timeline_data
= tab
.browser
.platform
.tracing_controller
.Stop()
152 timeline_model
= TimelineModel(timeline_data
)
153 threads
= timeline_model
.GetAllThreads()
154 for thread
in threads
:
155 if thread
.name
== _CR_RENDERER_MAIN
:
156 _AddTracingResults(thread
, results
)
158 def DidRunPage(self
, platform
):
159 if platform
.tracing_controller
.is_tracing_running
:
160 platform
.tracing_controller
.Stop()
163 class OilpanGCTimesForSmoothness(_OilpanGCTimesBase
):
165 super(OilpanGCTimesForSmoothness
, self
).__init
__()
166 self
._interaction
= None
168 def DidNavigateToPage(self
, page
, tab
):
169 runner
= action_runner
.ActionRunner(tab
)
170 self
._interaction
= runner
.CreateInteraction(_RUN_SMOOTH_ACTIONS
)
171 self
._interaction
.Begin()
173 def ValidateAndMeasurePage(self
, page
, tab
, results
):
174 self
._interaction
.End()
175 super(OilpanGCTimesForSmoothness
, self
).ValidateAndMeasurePage(
179 class OilpanGCTimesForBlinkPerf(_OilpanGCTimesBase
):
181 super(OilpanGCTimesForBlinkPerf
, self
).__init
__()
182 with
open(os
.path
.join(os
.path
.dirname(__file__
), '..', 'benchmarks',
183 'blink_perf.js'), 'r') as f
:
184 self
._blink
_perf
_js
= f
.read()
186 def WillNavigateToPage(self
, page
, tab
):
187 page
.script_to_evaluate_on_commit
= self
._blink
_perf
_js
188 super(OilpanGCTimesForBlinkPerf
, self
).WillNavigateToPage(page
, tab
)
190 def ValidateAndMeasurePage(self
, page
, tab
, results
):
191 tab
.WaitForJavaScriptExpression('testRunner.isDone', 600)
192 super(OilpanGCTimesForBlinkPerf
, self
).ValidateAndMeasurePage(
196 class OilpanGCTimesForInternals(OilpanGCTimesForBlinkPerf
):
198 super(OilpanGCTimesForInternals
, self
).__init
__()
201 def CustomizeBrowserOptions(cls
, options
):
202 # 'expose-internals-for-testing' can be enabled on content shell.
203 assert 'content-shell' in options
.browser_type
204 options
.AppendExtraBrowserArgs(['--expose-internals-for-testing',
205 '--js-flags=--expose-gc'])