""" Retrieves the system metrics and logs them into the monitors system. """
import json
import os
import subprocess
from numbers import Number
from typing import Optional
import monitors
from common import run_ffx_command, get_host_tool_path
TEMP_DIR = os.environ.get('TMPDIR', '/tmp')
FXT_FILE = os.path.join(TEMP_DIR, 'perf_trace.fxt')
JSON_FILE = os.path.join(TEMP_DIR, 'perf_trace.json')
METRIC_FILTERS = [
'gfx/ContiguousPooledMemoryAllocator::Allocate/size_bytes',
'gfx/SysmemProtectedPool/size',
'gfx/WindowedFramePredictor::GetPrediction/Predicted frame duration(ms)',
'gfx/WindowedFramePredictor::GetPrediction/Render time(ms)',
'gfx/WindowedFramePredictor::GetPrediction/Update time(ms)',
'memory_monitor/bandwidth_free/value',
'memory_monitor/free/free$',
'system_metrics/cpu_usage/average_cpu_percentage',
]
def start() -> None:
""" Starts the system tracing. """
run_ffx_command(cmd=('trace', 'start', '--background', '--categories',
'gfx,memory_monitor,system_metrics', '--buffer-size',
'32', '--buffering-mode', 'streaming'))
def stop(prefix: Optional[str] = None) -> None:
""" Stops the system tracing and logs the metrics into the monitors system
with an optional prefix as part of the metric names. """
run_ffx_command(cmd=('trace', 'stop', '--output', FXT_FILE))
_parse_trace(prefix)
def _parse_trace(prefix: Optional[str] = None) -> None:
subprocess.run([
get_host_tool_path('trace2json'), f'--input-file={FXT_FILE}',
f'--output-file={JSON_FILE}'
],
check=True)
with open(JSON_FILE, 'r') as file:
recorders = {}
for event in json.load(file)['traceEvents']:
if not 'args' in event:
continue
cat_name = [event['cat'], event['name']]
if prefix:
cat_name.insert(0, prefix)
args = event['args']
for arg in args:
if isinstance(args[arg], str):
cat_name.append(arg)
cat_name.append(args[arg])
for arg in args:
if isinstance(args[arg], Number):
name = cat_name.copy()
name.append(arg)
for f in METRIC_FILTERS:
if f in '/'.join(name) + '$':
if tuple(name) not in recorders:
recorders[tuple(name)] = monitors.average(
*name)
recorders[tuple(name)].record(args[arg])
if __name__ == '__main__':
_parse_trace()
monitors.dump(TEMP_DIR)