Commit d239c1be authored by nednguyen's avatar nednguyen Committed by Commit bot

[Telemetry] Add file handle & trace value.

Modify json_output_formatter to include trace values in the result output.

This is a partial land of Ethan's patch in https://codereview.chromium.org/545523002/.

BUG=

Review URL: https://codereview.chromium.org/663023005

Cr-Commit-Position: refs/heads/master@{#301558}
parent c119b2a9
...@@ -11,6 +11,7 @@ from telemetry.page import page_test ...@@ -11,6 +11,7 @@ from telemetry.page import page_test
from telemetry.page.actions import action_runner from telemetry.page.actions import action_runner
from telemetry.value import list_of_scalar_values from telemetry.value import list_of_scalar_values
from telemetry.value import scalar from telemetry.value import scalar
from telemetry.value import trace
from telemetry.web_perf import timeline_interaction_record as tir_module from telemetry.web_perf import timeline_interaction_record as tir_module
from telemetry.web_perf.metrics import smoothness from telemetry.web_perf.metrics import smoothness
...@@ -56,7 +57,7 @@ class SmoothnessController(object): ...@@ -56,7 +57,7 @@ class SmoothnessController(object):
RUN_SMOOTH_ACTIONS, is_smooth=True) RUN_SMOOTH_ACTIONS, is_smooth=True)
def Stop(self, tab): def Stop(self, tab):
# End the smooth marker for all smooth actions. # End the smooth marker for all smooth actions.
self._interaction.End() self._interaction.End()
# Stop tracing for smoothness metric. # Stop tracing for smoothness metric.
if tab.browser.platform.IsRawDisplayFrameRateSupported(): if tab.browser.platform.IsRawDisplayFrameRateSupported():
...@@ -69,7 +70,8 @@ class SmoothnessController(object): ...@@ -69,7 +70,8 @@ class SmoothnessController(object):
# Add results of smoothness metric. This computes the smoothness metric for # Add results of smoothness metric. This computes the smoothness metric for
# the time ranges of gestures, if there is at least one, else the the time # the time ranges of gestures, if there is at least one, else the the time
# ranges from the first action to the last action. # ranges from the first action to the last action.
results.AddValue(trace.TraceValue(
results.current_page, self._tracing_timeline_data))
renderer_thread = self._timeline_model.GetRendererThreadFromTabId( renderer_thread = self._timeline_model.GetRendererThreadFromTabId(
tab.id) tab.id)
run_smooth_actions_record = None run_smooth_actions_record = None
......
...@@ -3,20 +3,24 @@ ...@@ -3,20 +3,24 @@
# found in the LICENSE file. # found in the LICENSE file.
import json import json
import os
from telemetry.results import output_formatter from telemetry.results import output_formatter
from telemetry.util import file_handle
def ResultsAsDict(page_test_results, benchmark_metadata):
def ResultsAsDict(page_test_results, benchmark_metadata, output_dir):
"""Takes PageTestResults to a dict serializable to JSON. """Takes PageTestResults to a dict serializable to JSON.
To serialize results as JSON we first convert them to a dict that can be To serialize results as JSON we first convert them to a dict that can be
serialized by the json module. It also requires a benchmark_metadat object serialized by the json module. It also requires a benchmark_metadat object
for metadata to be integrated into the results (currently the benchmark for metadata to be integrated into the results (currently the benchmark
name). name). This function will also output trace files if they exist.
Args: Args:
page_test_results: a PageTestResults object page_test_results: a PageTestResults object
benchmark_metadata: a benchmark.BenchmarkMetadata object benchmark_metadata: a benchmark.BenchmarkMetadata object
output_dir: the directory that results are being output to.
""" """
result_dict = { result_dict = {
'format_version': '0.2', 'format_version': '0.2',
...@@ -28,23 +32,41 @@ def ResultsAsDict(page_test_results, benchmark_metadata): ...@@ -28,23 +32,41 @@ def ResultsAsDict(page_test_results, benchmark_metadata):
'pages': {p.id: p.AsDict() for p in _GetAllPages(page_test_results)} 'pages': {p.id: p.AsDict() for p in _GetAllPages(page_test_results)}
} }
file_ids_to_paths = _OutputTraceFiles(page_test_results, output_dir)
if file_ids_to_paths:
result_dict['files'] = file_ids_to_paths
return result_dict return result_dict
def _OutputTraceFiles(page_test_results, output_dir):
file_handles = page_test_results.all_file_handles
if not file_handles:
return {}
trace_dir = os.path.join(output_dir, 'trace_files')
if not os.path.isdir(trace_dir):
os.makedirs(trace_dir)
return file_handle.OutputFiles(file_handles, trace_dir)
def _GetAllPages(page_test_results): def _GetAllPages(page_test_results):
pages = set(page_run.page for page_run in pages = set(page_run.page for page_run in
page_test_results.all_page_runs) page_test_results.all_page_runs)
return pages return pages
class JsonOutputFormatter(output_formatter.OutputFormatter): class JsonOutputFormatter(output_formatter.OutputFormatter):
def __init__(self, output_stream, benchmark_metadata): def __init__(self, output_stream, output_dir, benchmark_metadata):
super(JsonOutputFormatter, self).__init__(output_stream) super(JsonOutputFormatter, self).__init__(output_stream)
self._benchmark_metadata = benchmark_metadata self._benchmark_metadata = benchmark_metadata
self._output_dir = output_dir
@property @property
def benchmark_metadata(self): def benchmark_metadata(self):
return self._benchmark_metadata return self._benchmark_metadata
def Format(self, page_test_results): def Format(self, page_test_results):
json.dump(ResultsAsDict(page_test_results, self.benchmark_metadata), json.dump(
ResultsAsDict(
page_test_results, self.benchmark_metadata, self._output_dir),
self.output_stream) self.output_stream)
self.output_stream.write('\n') self.output_stream.write('\n')
...@@ -3,14 +3,18 @@ ...@@ -3,14 +3,18 @@
# found in the LICENSE file. # found in the LICENSE file.
import json import json
import os import os
import shutil
import StringIO import StringIO
import unittest import unittest
import tempfile
from telemetry import benchmark from telemetry import benchmark
from telemetry.page import page_set from telemetry.page import page_set
from telemetry.results import json_output_formatter from telemetry.results import json_output_formatter
from telemetry.results import page_test_results from telemetry.results import page_test_results
from telemetry.value import scalar from telemetry.value import scalar
from telemetry.value import trace
from telemetry.timeline import tracing_timeline_data
def _MakePageSet(): def _MakePageSet():
...@@ -28,10 +32,15 @@ def _HasValueNamed(values, name): ...@@ -28,10 +32,15 @@ def _HasValueNamed(values, name):
class JsonOutputFormatterTest(unittest.TestCase): class JsonOutputFormatterTest(unittest.TestCase):
def setUp(self): def setUp(self):
self._output = StringIO.StringIO() self._output = StringIO.StringIO()
self._ouput_dir = tempfile.mkdtemp()
self._page_set = _MakePageSet() self._page_set = _MakePageSet()
self._formatter = json_output_formatter.JsonOutputFormatter(self._output, self._formatter = json_output_formatter.JsonOutputFormatter(
self._output, self._ouput_dir,
benchmark.BenchmarkMetadata('benchmark_name')) benchmark.BenchmarkMetadata('benchmark_name'))
def tearDown(self):
shutil.rmtree(self._ouput_dir)
def testOutputAndParse(self): def testOutputAndParse(self):
results = page_test_results.PageTestResults() results = page_test_results.PageTestResults()
...@@ -48,7 +57,7 @@ class JsonOutputFormatterTest(unittest.TestCase): ...@@ -48,7 +57,7 @@ class JsonOutputFormatterTest(unittest.TestCase):
def testAsDictBaseKeys(self): def testAsDictBaseKeys(self):
results = page_test_results.PageTestResults() results = page_test_results.PageTestResults()
d = json_output_formatter.ResultsAsDict(results, d = json_output_formatter.ResultsAsDict(results,
self._formatter.benchmark_metadata) self._formatter.benchmark_metadata, self._ouput_dir)
self.assertEquals(d['format_version'], '0.2') self.assertEquals(d['format_version'], '0.2')
self.assertEquals(d['benchmark_name'], 'benchmark_name') self.assertEquals(d['benchmark_name'], 'benchmark_name')
...@@ -61,11 +70,31 @@ class JsonOutputFormatterTest(unittest.TestCase): ...@@ -61,11 +70,31 @@ class JsonOutputFormatterTest(unittest.TestCase):
results.DidRunPage(self._page_set[0]) results.DidRunPage(self._page_set[0])
d = json_output_formatter.ResultsAsDict(results, d = json_output_formatter.ResultsAsDict(results,
self._formatter.benchmark_metadata) self._formatter.benchmark_metadata, self._ouput_dir)
self.assertTrue(_HasPage(d['pages'], self._page_set[0])) self.assertTrue(_HasPage(d['pages'], self._page_set[0]))
self.assertTrue(_HasValueNamed(d['per_page_values'], 'foo')) self.assertTrue(_HasValueNamed(d['per_page_values'], 'foo'))
def testAsDictWithTraceValue(self):
results = page_test_results.PageTestResults()
results.WillRunPage(self._page_set[0])
v0 = trace.TraceValue(
results.current_page,
tracing_timeline_data.TracingTimelineData({'event': 'test'}))
results.AddValue(v0)
results.DidRunPage(self._page_set[0])
d = json_output_formatter.ResultsAsDict(results,
self._formatter.benchmark_metadata, self._ouput_dir)
self.assertTrue(_HasPage(d['pages'], self._page_set[0]))
self.assertTrue(_HasValueNamed(d['per_page_values'], 'trace'))
self.assertEquals(len(d['files']), 1)
output_trace_path = d['files'].values()[0]
self.assertTrue(output_trace_path.startswith(self._ouput_dir))
self.assertTrue(os.path.exists(output_trace_path))
def testAsDictWithTwoPages(self): def testAsDictWithTwoPages(self):
results = page_test_results.PageTestResults() results = page_test_results.PageTestResults()
results.WillRunPage(self._page_set[0]) results.WillRunPage(self._page_set[0])
...@@ -79,7 +108,7 @@ class JsonOutputFormatterTest(unittest.TestCase): ...@@ -79,7 +108,7 @@ class JsonOutputFormatterTest(unittest.TestCase):
results.DidRunPage(self._page_set[1]) results.DidRunPage(self._page_set[1])
d = json_output_formatter.ResultsAsDict(results, d = json_output_formatter.ResultsAsDict(results,
self._formatter.benchmark_metadata) self._formatter.benchmark_metadata, self._ouput_dir)
self.assertTrue(_HasPage(d['pages'], self._page_set[0])) self.assertTrue(_HasPage(d['pages'], self._page_set[0]))
self.assertTrue(_HasPage(d['pages'], self._page_set[1])) self.assertTrue(_HasPage(d['pages'], self._page_set[1]))
...@@ -92,7 +121,7 @@ class JsonOutputFormatterTest(unittest.TestCase): ...@@ -92,7 +121,7 @@ class JsonOutputFormatterTest(unittest.TestCase):
results.AddSummaryValue(v) results.AddSummaryValue(v)
d = json_output_formatter.ResultsAsDict(results, d = json_output_formatter.ResultsAsDict(results,
self._formatter.benchmark_metadata) self._formatter.benchmark_metadata, self._ouput_dir)
self.assertFalse(d['pages']) self.assertFalse(d['pages'])
self.assertTrue(_HasValueNamed(d['summary_values'], 'baz')) self.assertTrue(_HasValueNamed(d['summary_values'], 'baz'))
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
import collections import collections
import copy import copy
import itertools
import traceback import traceback
from telemetry import value as value_module from telemetry import value as value_module
...@@ -61,6 +62,13 @@ class PageTestResults(object): ...@@ -61,6 +62,13 @@ class PageTestResults(object):
values += self._current_page_run.values values += self._current_page_run.values
return values return values
@property
def all_file_handles(self):
all_values = itertools.chain(
self.all_summary_values, self.all_page_specific_values)
return [fh for fh in map(lambda v: v.GetAssociatedFileHandle(), all_values)
if fh is not None]
@property @property
def all_summary_values(self): def all_summary_values(self):
return self._all_summary_values return self._all_summary_values
......
...@@ -142,7 +142,7 @@ def CreateResults(benchmark_metadata, options): ...@@ -142,7 +142,7 @@ def CreateResults(benchmark_metadata, options):
options.results_label, trace_tag=options.output_trace_tag)) options.results_label, trace_tag=options.output_trace_tag))
elif output_format == 'json': elif output_format == 'json':
output_formatters.append(json_output_formatter.JsonOutputFormatter( output_formatters.append(json_output_formatter.JsonOutputFormatter(
output_stream, benchmark_metadata)) output_stream, options.output_dir, benchmark_metadata))
elif output_format == 'chartjson': elif output_format == 'chartjson':
output_formatters.append( output_formatters.append(
chart_json_output_formatter.ChartJsonOutputFormatter( chart_json_output_formatter.ChartJsonOutputFormatter(
......
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import os
import shutil
_next_file_id = 0
class FileHandle(object):
def __init__(self, temp_file=None, absolute_path=None):
"""Constructs a FileHandle object.
This constructor should not be used by the user; rather it is preferred to
use the module-level GetAbsPath and FromTempFile functions.
Args:
temp_file: An instance of a temporary file object.
absolute_path: A path; should not be passed if tempfile is and vice-versa.
extension: A string that specifies the file extension. It must starts with
".".
"""
# Exactly one of absolute_path or temp_file must be specified.
assert (absolute_path is None) != (temp_file is None)
self._temp_file = temp_file
self._absolute_path = absolute_path
global _next_file_id
self._id = _next_file_id
_next_file_id += 1
@property
def id(self):
return self._id
@property
def extension(self):
return os.path.splitext(self.GetAbsPath())[1]
def GetAbsPath(self):
"""Returns the path to the pointed-to file relative to the given start path.
Args:
start: A string representing a starting path.
Returns:
A string giving the relative path from path to this file.
"""
if self._temp_file:
self._temp_file.close()
return self._temp_file.name
else:
return self._absolute_path
def FromTempFile(temp_file):
"""Constructs a FileHandle pointing to a temporary file.
Returns:
A FileHandle referring to a named temporary file.
"""
return FileHandle(temp_file)
def FromFilePath(path):
"""Constructs a FileHandle from an absolute file path.
Args:
path: A string giving the absolute path to a file.
Returns:
A FileHandle referring to the file at the specified path.
"""
return FileHandle(None, os.path.abspath(path))
def OutputFiles(file_handles, dir_name):
"""Outputs a list of file_handles by ID with a given dir_name and extension.
For the normal use case where we generate a collection of FileHandles
corresponding to temporary files, it is often necessary to collocate the
represented files into a single place. This function copies each file
referenced by an element of file_handles to a standardized location indicated
by dir_name.
Args:
file_handles: A list of file handles
dir_name: A string that specifies the directory to output the files.
Returns:
A dict mapping IDs to output files' paths.
"""
file_ids_to_paths = dict()
for fh in file_handles:
file_name = str(fh.id) + fh.extension
file_path = os.path.abspath(os.path.join(dir_name, file_name))
shutil.copy(fh.GetAbsPath(), file_path)
file_ids_to_paths[fh.id] = file_path
return file_ids_to_paths
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import os
import unittest
import shutil
import tempfile
from telemetry.util import file_handle
class FileHandleUnittest(unittest.TestCase):
def setUp(self):
self.temp_file_txt = tempfile.NamedTemporaryFile(
suffix='.txt', delete=False)
self.abs_path_html = tempfile.NamedTemporaryFile(
suffix='.html', delete=False).name
def tearDown(self):
os.remove(self.abs_path_html)
def testCreatingFileHandle(self):
fh1 = file_handle.FromTempFile(self.temp_file_txt)
self.assertEquals(fh1.extension, '.txt')
fh2 = file_handle.FromFilePath(self.abs_path_html)
self.assertEquals(fh2.extension, '.html')
self.assertNotEquals(fh1.id, fh2.id)
def testOutputFiles(self):
fh1 = file_handle.FromTempFile(self.temp_file_txt)
fh2 = file_handle.FromFilePath(self.abs_path_html)
tmpdir = tempfile.mkdtemp()
try:
file_ids_to_paths = file_handle.OutputFiles([fh1, fh2], tmpdir)
expected_output_file_1_path = os.path.join(tmpdir, str(fh1.id) + '.txt')
expected_output_file_2_path = os.path.join(tmpdir, str(fh2.id) + '.html')
self.assertEqual(file_ids_to_paths[fh1.id], expected_output_file_1_path)
self.assertEqual(file_ids_to_paths[fh2.id], expected_output_file_2_path)
# Test that the files are actually output.
self.assertTrue(os.path.exists(expected_output_file_1_path))
self.assertTrue(os.path.exists(expected_output_file_2_path))
finally:
shutil.rmtree(tmpdir)
...@@ -274,6 +274,10 @@ class Value(object): ...@@ -274,6 +274,10 @@ class Value(object):
return d return d
def GetAssociatedFileHandle(self):
"""Returns the file handle associated with this value (may be None)."""
return None
def ValueNameFromTraceAndChartName(trace_name, chart_name=None): def ValueNameFromTraceAndChartName(trace_name, chart_name=None):
"""Mangles a trace name plus optional chart name into a standard string. """Mangles a trace name plus optional chart name into a standard string.
......
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import tempfile
from telemetry import value as value_module
from telemetry.util import file_handle
import telemetry.web_components # pylint: disable=W0611
from trace_viewer.build import trace2html
class TraceValue(value_module.Value):
def __init__(self, page, tracing_timeline_data, important=False,
description=None):
"""A value that contains a TracingTimelineData object and knows how to
output it.
Adding TraceValues and outputting as JSON will produce a directory full of
HTML files called trace_files. Outputting as chart JSON will also produce
an index, files.html, linking to each of these files.
"""
super(TraceValue, self).__init__(
page, name='trace', units='', important=important,
description=description)
tf = tempfile.NamedTemporaryFile(delete=False, suffix='.html')
if page:
title = page.display_name
else:
title = ''
trace2html.WriteHTMLForTraceDataToFile(
[tracing_timeline_data.EventData()], title, tf)
tf.close()
self._file_handle = file_handle.FromTempFile(tf)
def GetAssociatedFileHandle(self):
return self._file_handle
def __repr__(self):
if self.page:
page_name = self.page.url
else:
page_name = None
return 'TraceValue(%s, %s)' % (page_name, self.name)
def GetBuildbotDataType(self, output_context):
return None
def GetBuildbotValue(self):
return None
def GetRepresentativeNumber(self):
return None
def GetRepresentativeString(self):
return None
@staticmethod
def GetJSONTypeName():
return 'trace'
@classmethod
def MergeLikeValuesFromSamePage(cls, values):
# TODO(eakuefner): Implement a MultiTraceValue: a Polymer-based,
# componentized, MultiTraceViwer-backed representation of more than one
# trace.
assert len(values) > 0
return values[0]
@classmethod
def MergeLikeValuesFromDifferentPages(cls, values,
group_by_name_suffix=False):
return None
def AsDict(self):
d = super(TraceValue, self).AsDict()
d['file_id'] = self._file_handle.id
return d
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import os
import unittest
from telemetry.page import page_set
from telemetry.timeline import tracing_timeline_data
from telemetry.value import trace
class TestBase(unittest.TestCase):
def setUp(self):
self.page_set = page_set.PageSet(file_path=os.path.dirname(__file__))
self.page_set.AddPageWithDefaultRunNavigate("http://www.bar.com/")
self.page_set.AddPageWithDefaultRunNavigate("http://www.baz.com/")
self.page_set.AddPageWithDefaultRunNavigate("http://www.foo.com/")
@property
def pages(self):
return self.page_set.pages
class ValueTest(TestBase):
def testAsDict(self):
v = trace.TraceValue(
None, tracing_timeline_data.TracingTimelineData({'test' : 1}))
fh_id = v.GetAssociatedFileHandle().id
d = v.AsDict()
self.assertEqual(d['file_id'], fh_id)
...@@ -2,16 +2,13 @@ ...@@ -2,16 +2,13 @@
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file. # found in the LICENSE file.
import logging
import os
from collections import defaultdict from collections import defaultdict
from telemetry.core import util
from telemetry.core.platform import tracing_category_filter from telemetry.core.platform import tracing_category_filter
from telemetry.core.platform import tracing_options from telemetry.core.platform import tracing_options
from telemetry.page import page_test from telemetry.page import page_test
from telemetry.timeline import model as model_module from telemetry.timeline import model as model_module
from telemetry.value import string as string_value_module from telemetry.value import trace
from telemetry.web_perf import timeline_interaction_record as tir_module from telemetry.web_perf import timeline_interaction_record as tir_module
from telemetry.web_perf.metrics import fast_metric from telemetry.web_perf.metrics import fast_metric
from telemetry.web_perf.metrics import responsiveness_metric from telemetry.web_perf.metrics import responsiveness_metric
...@@ -147,10 +144,6 @@ class TimelineBasedMeasurement(page_test.PageTest): ...@@ -147,10 +144,6 @@ class TimelineBasedMeasurement(page_test.PageTest):
choices=ALL_OVERHEAD_LEVELS, choices=ALL_OVERHEAD_LEVELS,
default=NO_OVERHEAD_LEVEL, default=NO_OVERHEAD_LEVEL,
help='How much overhead to incur during the measurement.') help='How much overhead to incur during the measurement.')
parser.add_option(
'--trace-dir', dest='trace_dir', type='string', default=None,
help=('Where to save the trace after the run. If this flag '
'is not set, the trace will not be saved.'))
def WillNavigateToPage(self, page, tab): def WillNavigateToPage(self, page, tab):
if not tab.browser.platform.tracing_controller.IsChromeTracingSupported( if not tab.browser.platform.tracing_controller.IsChromeTracingSupported(
...@@ -179,24 +172,14 @@ class TimelineBasedMeasurement(page_test.PageTest): ...@@ -179,24 +172,14 @@ class TimelineBasedMeasurement(page_test.PageTest):
def ValidateAndMeasurePage(self, page, tab, results): def ValidateAndMeasurePage(self, page, tab, results):
""" Collect all possible metrics and added them to results. """ """ Collect all possible metrics and added them to results. """
trace_result = tab.browser.platform.tracing_controller.Stop() trace_result = tab.browser.platform.tracing_controller.Stop()
trace_dir = self.options.trace_dir results.AddValue(trace.TraceValue(results.current_page, trace_result))
if trace_dir:
trace_file_path = util.GetSequentialFileName(
os.path.join(trace_dir, 'trace')) + '.json'
try:
with open(trace_file_path, 'w') as f:
trace_result.Serialize(f)
results.AddValue(string_value_module.StringValue(
page, 'trace_path', 'string', trace_file_path))
except IOError, e:
logging.error('Cannot open %s. %s' % (trace_file_path, e))
model = model_module.TimelineModel(trace_result) model = model_module.TimelineModel(trace_result)
renderer_thread = model.GetRendererThreadFromTabId(tab.id) renderer_thread = model.GetRendererThreadFromTabId(tab.id)
meta_metrics = _TimelineBasedMetrics( meta_metrics = _TimelineBasedMetrics(
model, renderer_thread, _GetMetricFromMetricType) model, renderer_thread, _GetMetricFromMetricType)
meta_metrics.AddResults(results) meta_metrics.AddResults(results)
def CleanUpAfterPage(self, page, tab): def CleanUpAfterPage(self, page, tab):
if tab.browser.platform.tracing_controller.is_tracing_running: if tab.browser.platform.tracing_controller.is_tracing_running:
tab.browser.platform.tracing_controller.Stop() tab.browser.platform.tracing_controller.Stop()
...@@ -241,6 +241,7 @@ class TimelineBasedMeasurementTest(page_test_test_case.PageTestTestCase): ...@@ -241,6 +241,7 @@ class TimelineBasedMeasurementTest(page_test_test_case.PageTestTestCase):
'SlowThreadJsRun-fast-scavenger_outside_idle', 'SlowThreadJsRun-fast-scavenger_outside_idle',
'SlowThreadJsRun-fast-total_garbage_collection', 'SlowThreadJsRun-fast-total_garbage_collection',
'SlowThreadJsRun-fast-total_garbage_collection_outside_idle', 'SlowThreadJsRun-fast-total_garbage_collection_outside_idle',
'trace',
]) ])
if platform.GetHostPlatform().GetOSName() != 'win': if platform.GetHostPlatform().GetOSName() != 'win':
# CPU metric is only supported non-Windows platforms. # CPU metric is only supported non-Windows platforms.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment