blob: 170755f2d2c1c0a165fe9e31e4e8034842f9f9f0 [file] [log] [blame]
import threading
from autotest_lib.client.common_lib.cros import system_metrics_collector
from autotest_lib.client.common_lib.cros.cfm.metrics import (
media_metrics_collector)
class PerfMetricsCollector(object):
"""
Metrics collector that runs in seprate thread than the caller.
"""
def __init__(self, system_facade, cfm_facade, writer_function,
additional_system_metrics=[]):
"""
Constructor.
@param system_facade facade object to access system utils.
@param cfm_facade facade object to access cfm utils.
@param writer_function function called to collected metrics.
@param additional_system_metrics Additional metrics to collect.
"""
metric_set = system_metrics_collector.create_default_metric_set(
system_facade)
for metric in additional_system_metrics:
metric_set.append(metric)
self._system_metrics_collector = (
system_metrics_collector.SystemMetricsCollector(system_facade,
metric_set))
# Media metrics
data_point_collector = media_metrics_collector.DataPointCollector(
cfm_facade)
self._media_metrics_collector = (media_metrics_collector
.MetricsCollector(data_point_collector))
self._writer_function = writer_function
# Collector thread.
self._collector_thread = threading.Thread(
target=self._collect_snapshots_until_stopped)
self._stop = threading.Event()
def start(self):
"""
Starts metrics collection.
"""
self._system_metrics_collector.pre_collect()
self._collector_thread.start()
def stop(self):
"""
Stops metrics collection.
"""
self._stop.set()
self._system_metrics_collector.post_collect()
def upload_metrics(self):
"""
Uploads collected metrics.
"""
self._upload_system_metrics()
self._upload_media_metrics()
def _collect_snapshots_until_stopped(self):
while not self._stop.wait(10):
self._system_metrics_collector.collect_snapshot()
self._media_metrics_collector.collect_snapshot()
def _upload_system_metrics(self):
self._system_metrics_collector.write_metrics(self._writer_function)
def _get_jmi_data(self, data_type):
"""
Gets jmi data for the given data type.
@param data_type: Type of data to be retrieved from jmi data logs.
@return Data for given data type from jmidata log.
"""
timestamped_values = self._media_metrics_collector.get_metric(data_type)
# Strip timestamps.
values = [x[1] for x in timestamped_values]
# Each entry in values is a list, extract the raw values:
res = []
for value_list in values:
res.extend(value_list)
# Ensure we always return at least one element, or perf uploads will
# be sad.
return res or [0]
def _get_last_value(self, data_type):
"""
Gets last value of a list of numbers.
@param data_type: Type of data to be retrieved from jmi data log.
@return The last value in the jmidata for the specified data_type. 0 if
there are no values in the jmidata for this data_type.
"""
data = self._get_jmi_data(data_type)
if not data:
return 0
return data[-1]
def _upload_media_metrics(self):
"""
Write jmidata results to results-chart.json file for Perf Dashboard.
"""
# Video/Sender metrics
self._writer_function(
description='avg_encode_ms',
value=self._get_jmi_data(media_metrics_collector.AVG_ENCODE_MS),
units='ms',
higher_is_better=False)
self._writer_function(
description='vid_out_frame_height', # video_out_res
value=self._get_jmi_data(media_metrics_collector.
VIDEO_SENT_FRAME_HEIGHT),
units='px',
higher_is_better=True)
self._writer_function(
description='vid_out_frame_width',
value=self._get_jmi_data(media_metrics_collector.
VIDEO_SENT_FRAME_WIDTH),
units='px',
higher_is_better=True)
self._writer_function(
description='vid_out_framerate_captured',
value=self._get_jmi_data(media_metrics_collector.
FRAMERATE_CAPTURED),
units='fps',
higher_is_better=True)
self._writer_function(
description='vid_out_framerate_encoded',
value=self._get_jmi_data(media_metrics_collector.
FRAMERATE_ENCODED),
units='fps',
higher_is_better=True)
self._writer_function(
description='vid_out_sent_packets',
value=self._get_last_value(media_metrics_collector.
VIDEO_SENT_PACKETS),
units='packets',
higher_is_better=True)
# Video/Receiver metrics
self._writer_function(
description='vid_in_framerate_received',
value=self._get_jmi_data(media_metrics_collector.
FRAMERATE_NETWORK_RECEIVED),
units='fps',
higher_is_better=True)
self._writer_function(
description='vid_in_framerate_decoded',
value=self._get_jmi_data(media_metrics_collector.FRAMERATE_DECODED),
units='fps',
higher_is_better=True)
self._writer_function(
description='vid_in_framerate_to_renderer',
value=self._get_jmi_data(media_metrics_collector.
FRAMERATE_TO_RENDERER),
units='fps',
higher_is_better=True)
self._writer_function(
description='video_in_frame_heigth', # video_in_res
value=self._get_jmi_data(media_metrics_collector.
VIDEO_RECEIVED_FRAME_HEIGHT),
units='px',
higher_is_better=True)
self._writer_function(
description='vid_in_frame_width',
value=self._get_jmi_data(media_metrics_collector.
VIDEO_RECEIVED_FRAME_WIDTH),
units='px',
higher_is_better=True)
# Adaptation metrics
self._writer_function(
description='vid_out_adapt_changes',
value=self._get_last_value(media_metrics_collector.
ADAPTATION_CHANGES),
units='count',
higher_is_better=False)
self._writer_function(
description='vid_out_adapt_reasons',
value=self._get_jmi_data(media_metrics_collector.ADAPTATION_REASON),
units='reasons',
higher_is_better=False)
# System metrics
self._writer_function(
description='cpu_usage_jmi',
value=self._get_jmi_data(media_metrics_collector.
CPU_PERCENT_OF_TOTAL),
units='percent',
higher_is_better=False)
self._writer_function(
description='process_js_memory',
value=[(x / (1024 * 1024)) for x in self._get_jmi_data(
media_metrics_collector.PROCESS_JS_MEMORY_USED)],
units='MB',
higher_is_better=False)
self._writer_function(
description='renderer_cpu_usage',
value=self._get_jmi_data(
media_metrics_collector.RENDERER_CPU_PERCENT_OF_TOTAL),
units='percent',
higher_is_better=False)
self._writer_function(
description='browser_cpu_usage',
value=self._get_jmi_data(
media_metrics_collector.BROWSER_CPU_PERCENT_OF_TOTAL),
units='percent',
higher_is_better=False)
self._writer_function(
description='gpu_cpu_usage',
value=self._get_jmi_data(
media_metrics_collector.GPU_PERCENT_OF_TOTAL),
units='percent',
higher_is_better=False)
# Other
self._writer_function(
description='active_streams',
value=self._get_jmi_data(media_metrics_collector.
NUMBER_OF_ACTIVE_INCOMING_VIDEO_STREAMS),
units='count',
higher_is_better=True)