summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorernstm@chromium.org <ernstm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-16 11:49:43 +0000
committerernstm@chromium.org <ernstm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-16 11:49:43 +0000
commitbb82d679961b5c4ca2d938af15bd0b38d3e72d22 (patch)
tree495928688f666122496604501837bc8133668aac
parent86e4fa6746b34bbdd84901debb64d6de511699fc (diff)
downloadchromium_src-bb82d679961b5c4ca2d938af15bd0b38d3e72d22.zip
chromium_src-bb82d679961b5c4ca2d938af15bd0b38d3e72d22.tar.gz
chromium_src-bb82d679961b5c4ca2d938af15bd0b38d3e72d22.tar.bz2
Made trace profiler work with trace-based benchmarks.
R=tonyg BUG=282712 Review URL: https://chromiumcodereview.appspot.com/23902027 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@223330 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--tools/perf/measurements/rasterize_and_record.py5
-rw-r--r--tools/perf/measurements/smoothness.py11
-rw-r--r--tools/perf/metrics/timeline.py4
-rw-r--r--tools/telemetry/telemetry/core/backends/browser_backend.py3
-rw-r--r--tools/telemetry/telemetry/core/backends/chrome/chrome_browser_backend.py8
-rw-r--r--tools/telemetry/telemetry/core/backends/chrome/tracing_backend.py119
-rw-r--r--tools/telemetry/telemetry/core/backends/chrome/tracing_backend_unittest.py46
-rw-r--r--tools/telemetry/telemetry/core/browser.py4
-rw-r--r--tools/telemetry/telemetry/core/platform/profiler/strace_profiler.py3
-rw-r--r--tools/telemetry/telemetry/core/platform/profiler/trace_profiler.py4
10 files changed, 167 insertions, 40 deletions
diff --git a/tools/perf/measurements/rasterize_and_record.py b/tools/perf/measurements/rasterize_and_record.py
index 4ed5a09..b5bc613 100644
--- a/tools/perf/measurements/rasterize_and_record.py
+++ b/tools/perf/measurements/rasterize_and_record.py
@@ -148,7 +148,7 @@ class RasterizeAndRecord(page_measurement.PageMeasurement):
});
""")
- tab.browser.StartTracing('webkit,webkit.console,benchmark', 60)
+ tab.browser.StartTracing('webkit.console,benchmark', 60)
self._metrics.Start()
tab.ExecuteJavaScript("""
@@ -166,10 +166,9 @@ class RasterizeAndRecord(page_measurement.PageMeasurement):
time.sleep(float(self.options.stop_wait_time))
tab.ExecuteJavaScript('console.timeEnd("measureNextFrame")')
- tab.browser.StopTracing()
self._metrics.Stop()
+ timeline = tab.browser.StopTracing().AsTimelineModel()
- timeline = tab.browser.GetTraceResultAndReset().AsTimelineModel()
collector = StatsCollector(timeline)
collector.GatherRenderingStats()
diff --git a/tools/perf/measurements/smoothness.py b/tools/perf/measurements/smoothness.py
index a26ba68..f44feef 100644
--- a/tools/perf/measurements/smoothness.py
+++ b/tools/perf/measurements/smoothness.py
@@ -28,6 +28,7 @@ class Smoothness(page_measurement.PageMeasurement):
super(Smoothness, self).__init__('smoothness')
self.force_enable_threaded_compositing = False
self._metrics = None
+ self._trace_result = None
def AddCommandLineOptions(self, parser):
parser.add_option('--report-all-results', dest='report_all_results',
@@ -43,9 +44,7 @@ class Smoothness(page_measurement.PageMeasurement):
return hasattr(page, 'smoothness')
def WillRunAction(self, page, tab, action):
- # TODO(ernstm): remove 'webkit' category when
- # https://codereview.chromium.org/23848006/ has landed.
- tab.browser.StartTracing('webkit,webkit.console,benchmark', 60)
+ tab.browser.StartTracing('webkit.console,benchmark', 60)
if tab.browser.platform.IsRawDisplayFrameRateSupported():
tab.browser.platform.StartRawDisplayFrameRateMeasurement()
self._metrics = smoothness.SmoothnessMetrics(tab)
@@ -59,7 +58,7 @@ class Smoothness(page_measurement.PageMeasurement):
tab.browser.platform.StopRawDisplayFrameRateMeasurement()
if not action.CanBeBound():
self._metrics.Stop()
- tab.browser.StopTracing()
+ self._trace_result = tab.browser.StopTracing()
def FindTimelineMarker(self, timeline):
events = [s for
@@ -80,8 +79,8 @@ class Smoothness(page_measurement.PageMeasurement):
smoothness.CalcFirstPaintTimeResults(results, tab)
- timeline = tab.browser.GetTraceResultAndReset().AsTimelineModel()
- timeline_marker = self.FindTimelineMarker(timeline)
+ timeline_marker = self.FindTimelineMarker(
+ self._trace_result.AsTimelineModel())
benchmark_stats = GpuRenderingStats(timeline_marker,
rendering_stats_deltas,
self._metrics.is_using_gpu_benchmarking)
diff --git a/tools/perf/metrics/timeline.py b/tools/perf/metrics/timeline.py
index 6462646..6d9ef26 100644
--- a/tools/perf/metrics/timeline.py
+++ b/tools/perf/metrics/timeline.py
@@ -38,8 +38,7 @@ class TimelineMetric(Metric):
console.timeEnd("__loading_measurement_was_here__");
""")
- tab.browser.StopTracing()
- trace_result = tab.browser.GetTraceResultAndReset()
+ trace_result = tab.browser.StopTracing()
self._model = trace_result.AsTimelineModel()
events = [s for
s in self._model.GetAllEventsOfName(
@@ -68,4 +67,3 @@ class TimelineMetric(Metric):
results.Add(event_name, 'ms', total)
results.Add(event_name + '_max', 'ms', biggest_jank)
results.Add(event_name + '_avg', 'ms', total / len(times))
-
diff --git a/tools/telemetry/telemetry/core/backends/browser_backend.py b/tools/telemetry/telemetry/core/backends/browser_backend.py
index 2c6f058..22df0b1 100644
--- a/tools/telemetry/telemetry/core/backends/browser_backend.py
+++ b/tools/telemetry/telemetry/core/backends/browser_backend.py
@@ -66,9 +66,6 @@ class BrowserBackend(object):
def StopTracing(self):
raise NotImplementedError()
- def GetTraceResultAndReset(self):
- raise NotImplementedError()
-
def GetRemotePort(self, _):
return util.GetAvailableLocalPort()
diff --git a/tools/telemetry/telemetry/core/backends/chrome/chrome_browser_backend.py b/tools/telemetry/telemetry/core/backends/chrome/chrome_browser_backend.py
index 579cef4..aeadf92 100644
--- a/tools/telemetry/telemetry/core/backends/chrome/chrome_browser_backend.py
+++ b/tools/telemetry/telemetry/core/backends/chrome/chrome_browser_backend.py
@@ -222,13 +222,11 @@ class ChromeBrowserBackend(browser_backend.BrowserBackend):
"""
if self._tracing_backend is None:
self._tracing_backend = tracing_backend.TracingBackend(self._port)
- self._tracing_backend.BeginTracing(custom_categories, timeout)
+ return self._tracing_backend.StartTracing(custom_categories, timeout)
def StopTracing(self):
- self._tracing_backend.EndTracing()
-
- def GetTraceResultAndReset(self):
- return self._tracing_backend.GetTraceResultAndReset()
+ """ Stops tracing and returns the result as TraceResult object. """
+ return self._tracing_backend.StopTracing()
def GetProcessName(self, cmd_line):
"""Returns a user-friendly name for the process of the given |cmd_line|."""
diff --git a/tools/telemetry/telemetry/core/backends/chrome/tracing_backend.py b/tools/telemetry/telemetry/core/backends/chrome/tracing_backend.py
index 4d0c68a..f080280 100644
--- a/tools/telemetry/telemetry/core/backends/chrome/tracing_backend.py
+++ b/tools/telemetry/telemetry/core/backends/chrome/tracing_backend.py
@@ -8,7 +8,6 @@ import logging
import socket
import threading
-
from telemetry.core.backends.chrome import trace_result
from telemetry.core.backends.chrome import websocket
from telemetry.core.backends.chrome import websocket_browser_connection
@@ -65,16 +64,97 @@ class RawTraceResultImpl(object):
def AsTimelineModel(self):
return model.TimelineModel(self._tracing_data)
+class CategoryFilter(object):
+ def __init__(self, filter_string):
+ self.excluded = set()
+ self.included = set()
+ self.disabled = set()
+ self.contains_wildcards = False
+
+ if not filter_string:
+ return
+
+ if '*' in filter_string or '?' in filter_string:
+ self.contains_wildcards = True
+
+ filter_set = set(filter_string.split(','))
+ for category in filter_set:
+ if category == '':
+ continue
+ if category[0] == '-':
+ category = category[1:]
+ self.excluded.add(category)
+ elif category.startswith('disabled-by-default-'):
+ self.disabled.add(category)
+ else:
+ self.included.add(category)
+
+ def IsSubset(self, other):
+ """ Determine if filter A (self) is a subset of filter B (other).
+ Returns True if A is a subset of B, False if A is not a subset of B,
+ and None if we can't tell for sure.
+ """
+ # We don't handle filters with wildcards in this test.
+ if self.contains_wildcards or other.contains_wildcards:
+ return None
+
+ # Disabled categories get into a trace if and only if they are contained in
+ # the 'disabled' set. Return False if A's disabled set is a superset of B's
+ # disabled set.
+ if len(self.disabled):
+ if self.disabled > other.disabled:
+ return False
+
+ if len(self.included) and len(other.included):
+ # A and B have explicit include lists. If A includes something that B
+ # doesn't, return False.
+ if not self.included <= other.included:
+ return False
+ elif len(self.included):
+ # Only A has an explicit include list. If A includes something that B
+ # excludes, return False.
+ if len(self.included.intersection(other.excluded)):
+ return False
+ elif len(other.included):
+ # Only B has an explicit include list. We don't know which categories are
+ # contained in the default list, so return None.
+ return None
+ else:
+ # None of the filter have explicit include list. If B excludes categories
+ # that A doesn't exclude, return False.
+ if not other.excluded <= self.excluded:
+ return False
+
+ return True
+
class TracingBackend(object):
def __init__(self, devtools_port):
self._conn = websocket_browser_connection.WebSocketBrowserConnection(
devtools_port)
self._thread = None
+ self._category_filter = None
+ self._nesting = 0
self._tracing_data = []
- def BeginTracing(self, custom_categories=None, timeout=10):
+ def _IsTracing(self):
+ return self._thread != None
+
+ def StartTracing(self, custom_categories=None, timeout=10):
+ """ Starts tracing on the first nested call and returns True. Returns False
+ and does nothing on subsequent nested calls.
+ """
+ self._nesting += 1
+ if self._IsTracing():
+ new_category_filter = CategoryFilter(custom_categories)
+ is_subset = new_category_filter.IsSubset(self._category_filter)
+ assert(is_subset != False)
+ if is_subset == None:
+ logging.warning('Cannot determine if category filter of nested ' +
+ 'StartTracing call is subset of current filter.')
+ return False
self._CheckNotificationSupported()
req = {'method': 'Tracing.start'}
+ self._category_filter = CategoryFilter(custom_categories)
if custom_categories:
req['params'] = {'categories': custom_categories}
self._conn.SendRequest(req, timeout)
@@ -82,22 +162,39 @@ class TracingBackend(object):
# data, until Tracing.end is called.
self._thread = threading.Thread(target=self._TracingReader)
self._thread.start()
+ return True
+
+ def StopTracing(self):
+ """ Stops tracing on the innermost (!) nested call, because we cannot get
+ results otherwise. Resets _tracing_data on the outermost nested call.
+ Returns the result of the trace, as TraceResult object.
+ """
+ self._nesting -= 1
+ assert self._nesting >= 0
+ if self._IsTracing():
+ req = {'method': 'Tracing.end'}
+ self._conn.SendRequest(req)
+ self._thread.join()
+ self._thread = None
+ if self._nesting == 0:
+ self._category_filter = None
+ return self._GetTraceResultAndReset()
+ else:
+ return self._GetTraceResult()
- def EndTracing(self):
- req = {'method': 'Tracing.end'}
- self._conn.SendRequest(req)
- self._thread.join()
- self._thread = None
-
- def GetTraceResultAndReset(self):
- assert not self._thread
+ def _GetTraceResult(self):
+ assert not self._IsTracing()
if self._tracing_data and type(self._tracing_data[0]) in [str, unicode]:
result_impl = TraceResultImpl(self._tracing_data)
else:
result_impl = RawTraceResultImpl(self._tracing_data)
- self._tracing_data = []
return trace_result.TraceResult(result_impl)
+ def _GetTraceResultAndReset(self):
+ result = self._GetTraceResult()
+ self._tracing_data = []
+ return result
+
def _TracingReader(self):
while self._conn.socket:
try:
diff --git a/tools/telemetry/telemetry/core/backends/chrome/tracing_backend_unittest.py b/tools/telemetry/telemetry/core/backends/chrome/tracing_backend_unittest.py
index afbb3b8..b2b0fa3 100644
--- a/tools/telemetry/telemetry/core/backends/chrome/tracing_backend_unittest.py
+++ b/tools/telemetry/telemetry/core/backends/chrome/tracing_backend_unittest.py
@@ -11,6 +11,52 @@ from telemetry.core import util
from telemetry.core.backends.chrome import tracing_backend
from telemetry.unittest import tab_test_case
+class CategoryFilterTest(unittest.TestCase):
+ def testIsSubset(self):
+ b = tracing_backend.CategoryFilter(None)
+ a = tracing_backend.CategoryFilter(None)
+ self.assertEquals(a.IsSubset(b), True)
+
+ b = tracing_backend.CategoryFilter(None)
+ a = tracing_backend.CategoryFilter("test1,test2")
+ self.assertEquals(a.IsSubset(b), True)
+
+ b = tracing_backend.CategoryFilter(None)
+ a = tracing_backend.CategoryFilter("-test1,-test2")
+ self.assertEquals(a.IsSubset(b), True)
+
+ b = tracing_backend.CategoryFilter("test1,test2")
+ a = tracing_backend.CategoryFilter(None)
+ self.assertEquals(a.IsSubset(b), None)
+
+ b = tracing_backend.CategoryFilter(None)
+ a = tracing_backend.CategoryFilter("test*")
+ self.assertEquals(a.IsSubset(b), None)
+
+ b = tracing_backend.CategoryFilter("test?")
+ a = tracing_backend.CategoryFilter(None)
+ self.assertEquals(a.IsSubset(b), None)
+
+ b = tracing_backend.CategoryFilter("test1")
+ a = tracing_backend.CategoryFilter("test1,test2")
+ self.assertEquals(a.IsSubset(b), False)
+
+ b = tracing_backend.CategoryFilter("-test1")
+ a = tracing_backend.CategoryFilter("test1")
+ self.assertEquals(a.IsSubset(b), False)
+
+ b = tracing_backend.CategoryFilter("test1,test2")
+ a = tracing_backend.CategoryFilter("test2,test1")
+ self.assertEquals(a.IsSubset(b), True)
+
+ b = tracing_backend.CategoryFilter("-test1,-test2")
+ a = tracing_backend.CategoryFilter("-test2")
+ self.assertEquals(a.IsSubset(b), False)
+
+ b = tracing_backend.CategoryFilter("disabled-by-default-test1")
+ a = tracing_backend.CategoryFilter(
+ "disabled-by-default-test1,disabled-by-default-test2")
+ self.assertEquals(a.IsSubset(b), False)
class TracingBackendTest(tab_test_case.TabTestCase):
def _StartServer(self):
diff --git a/tools/telemetry/telemetry/core/browser.py b/tools/telemetry/telemetry/core/browser.py
index bdf26d4..c436794 100644
--- a/tools/telemetry/telemetry/core/browser.py
+++ b/tools/telemetry/telemetry/core/browser.py
@@ -256,10 +256,6 @@ class Browser(object):
def StopTracing(self):
return self._browser_backend.StopTracing()
- def GetTraceResultAndReset(self):
- """Returns the result of the trace, as TraceResult object."""
- return self._browser_backend.GetTraceResultAndReset()
-
def Start(self):
browser_options = self._browser_backend.browser_options
if browser_options.clear_sytem_cache_for_browser_and_profile_on_start:
diff --git a/tools/telemetry/telemetry/core/platform/profiler/strace_profiler.py b/tools/telemetry/telemetry/core/platform/profiler/strace_profiler.py
index f270106..c22140b 100644
--- a/tools/telemetry/telemetry/core/platform/profiler/strace_profiler.py
+++ b/tools/telemetry/telemetry/core/platform/profiler/strace_profiler.py
@@ -241,8 +241,7 @@ class StraceProfiler(profiler.Profiler):
for single_process in self._process_profilers:
out_json.extend(single_process.CollectProfile())
- self._browser_backend.StopTracing()
- model = self._browser_backend.GetTraceResultAndReset().AsTimelineModel()
+ model = self._browser_backend.StopTracing().AsTimelineModel()
out_json.extend(_GenerateTraceMetadata(model))
with open(self._output_file, 'w') as f:
diff --git a/tools/telemetry/telemetry/core/platform/profiler/trace_profiler.py b/tools/telemetry/telemetry/core/platform/profiler/trace_profiler.py
index 122db9c..6262847 100644
--- a/tools/telemetry/telemetry/core/platform/profiler/trace_profiler.py
+++ b/tools/telemetry/telemetry/core/platform/profiler/trace_profiler.py
@@ -24,11 +24,9 @@ class TraceProfiler(profiler.Profiler):
return True
def CollectProfile(self):
- self._browser_backend.StopTracing()
-
print 'Processing trace...'
- trace_result = self._browser_backend.GetTraceResultAndReset()
+ trace_result = self._browser_backend.StopTracing()
trace_file = '%s.json' % self._output_path