Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(386)

Unified Diff: tools/telemetry/telemetry/core/backends/chrome/tracing_backend.py

Issue 23902027: telemetry: Make trace profiler work with trace-based benchmarks. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add subset test for category filters. Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: tools/telemetry/telemetry/core/backends/chrome/tracing_backend.py
diff --git a/tools/telemetry/telemetry/core/backends/chrome/tracing_backend.py b/tools/telemetry/telemetry/core/backends/chrome/tracing_backend.py
index 4d0c68a8a3edb617314407f60d0a8624407e4a14..f0802802dadb102c44c40ec0f650eb07b01106a7 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:

Powered by Google App Engine
This is Rietveld 408576698