blob: a7b8733ced2bbdf99e441f2f0a7999dd317e1099 [file] [edit]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// TODO(https://fxbug.dev/84961): Fix null safety and remove this language version.
// @dart=2.9
import 'dart:io' show File;
import 'dart:convert';
import 'package:sl4f/trace_processing.dart';
import 'package:test/test.dart';
import 'helpers.dart';
const _trace2jsonPath = 'runtime_deps/trace2json';
void main() {
enableLoggingOutput();
// We run the fuchsia_microbenchmarks process multiple times. That is
// useful for tests that exhibit between-process variation in results
// (e.g. due to memory layout chosen when a process starts) -- it
// reduces the variation in the average that we report.
const int processRuns = 6;
// We override the default number of within-process iterations of
// each test case and use a lower value. This reduces the overall
// time taken and reduces the chance that these invocations hit
// Infra Swarming tasks' IO timeout (swarming_io_timeout_secs --
// the amount of time that a task is allowed to run without
// producing log output).
const int iterationsPerTestPerProcess = 120;
// For running with tracing enabled we run the following tests:
//
// - The Tracing suite, which creates exercises the trace-engine code via
// TRACE macros
// - Syscall/Null, Syscall/ManyArgs, and Channel/WriteRead which exercise
// writing events to the kernel trace buffer
const filterRegex =
"'(^Tracing/)|(^Syscall/Null\$)|(^Syscall/ManyArgs\$)|(^Channel/WriteRead/1024bytes/1handles\$)'";
test('fuchsia_microbenchmarks', () async {
final helper = await PerfTestHelper.make();
await helper.runTestComponent(
packageName: 'fuchsia_microbenchmarks',
componentName: 'fuchsia_microbenchmarks.cm',
commandArgs: '-p --quiet --out ${PerfTestHelper.componentOutputPath}'
' --runs $iterationsPerTestPerProcess',
processRuns: processRuns,
expectedMetricNamesFile: 'fuchsia.microbenchmarks.txt');
}, timeout: Timeout.none);
// Modify the given fuchsiaperf.json file to add a suffix to all of
// the test_suite fields, to allow distinguishing between test
// variants.
void addTestSuiteSuffix(File resultsFile, String suffix) {
final jsonData = jsonDecode(resultsFile.readAsStringSync());
for (final testResult in jsonData) {
testResult['test_suite'] += suffix;
}
resultsFile.writeAsStringSync(jsonEncode(jsonData));
}
// Run some of the microbenchmarks with tracing enabled to measure the
// overhead of tracing.
test('fuchsia_microbenchmarks_tracing_categories_enabled', () async {
final helper = await PerfTestHelper.make();
final List<File> resultsFiles = [];
for (var process = 0; process < processRuns; ++process) {
final traceSession = await helper.performance.initializeTracing(
categories: ['kernel', 'benchmark'], bufferSize: 36);
await traceSession.start();
final resultsFile = await helper.runTestComponentReturningResultsFile(
packageName: 'fuchsia_microbenchmarks',
componentName: 'fuchsia_microbenchmarks.cm',
commandArgs: '-p --quiet'
' --out ${PerfTestHelper.componentOutputPath}'
' --runs $iterationsPerTestPerProcess'
' --filter $filterRegex --enable-tracing',
resultsFileSuffix: '_process$process');
addTestSuiteSuffix(resultsFile, '.tracing');
resultsFiles.add(resultsFile);
await traceSession.stop();
const testName = 'fuchsia_microbenchmarks_tracing_categories_enabled';
final fxtTraceFile = await traceSession.terminateAndDownload(testName);
final jsonTraceFile = await helper.performance
.convertTraceFileToJson(_trace2jsonPath, fxtTraceFile);
// Check that the trace contains the expected trace events.
final Model model = await createModelFromFile(jsonTraceFile);
var events = filterEvents(getAllEvents(model), category: 'benchmark');
for (final eventName in [
'InstantEvent',
'ScopedDuration',
'DurationBegin'
]) {
expect(events.where((event) => event.name == eventName).length,
iterationsPerTestPerProcess,
reason: 'Mismatch for $eventName');
}
events = filterEvents(getAllEvents(model), category: 'kernel:syscall');
for (final eventName in ['syscall_test_0', 'syscall_test_8']) {
expect(events.where((event) => event.name == eventName).length,
iterationsPerTestPerProcess,
reason: 'Mismatch for $eventName');
}
}
await helper.processResultsSummarized(resultsFiles,
expectedMetricNamesFile: 'fuchsia.microbenchmarks.tracing.txt');
}, timeout: Timeout.none);
// Run some of the microbenchmarks with tracing enabled but each category
// disabled to measure the overhead of a trace event with the category turned
// off.
test('fuchsia_microbenchmarks_tracing_categories_disabled', () async {
final helper = await PerfTestHelper.make();
final List<File> resultsFiles = [];
for (var process = 0; process < processRuns; ++process) {
final traceSession = await helper.performance.initializeTracing(
categories: ['nonexistent_category'], bufferSize: 36);
await traceSession.start();
final resultsFile = await helper.runTestComponentReturningResultsFile(
packageName: 'fuchsia_microbenchmarks',
componentName: 'fuchsia_microbenchmarks.cm',
commandArgs: '-p --quiet'
' --out ${PerfTestHelper.componentOutputPath}'
' --runs $iterationsPerTestPerProcess'
' --filter $filterRegex --enable-tracing',
resultsFileSuffix: '_process$process');
addTestSuiteSuffix(resultsFile, '.tracing_categories_disabled');
resultsFiles.add(resultsFile);
await traceSession.stop();
const testName = 'fuchsia_microbenchmarks_tracing_categories_disabled';
final fxtTraceFile = await traceSession.terminateAndDownload(testName);
final jsonTraceFile = await helper.performance
.convertTraceFileToJson(_trace2jsonPath, fxtTraceFile);
// All the real tracing categories are disabled, so we should
// get no trace events.
final Model model = await createModelFromFile(jsonTraceFile);
expect(getAllEvents(model), []);
}
await helper.processResultsSummarized(resultsFiles,
expectedMetricNamesFile:
'fuchsia.microbenchmarks.tracing_categories_disabled.txt');
}, timeout: Timeout.none);
}