diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt index b2adc068668..1d565876077 100644 --- a/pkg/front_end/test/spell_checking_list_tests.txt +++ b/pkg/front_end/test/spell_checking_list_tests.txt @@ -375,6 +375,7 @@ ha hackish hardcoding hardly +hardware hb hc helpfully @@ -750,6 +751,7 @@ subs subtool subtools successes +sudo sueta suggest summarization @@ -826,6 +828,7 @@ upgrade upload upstream upward +useless uuid val verbatim diff --git a/pkg/front_end/tool/benchmarker.dart b/pkg/front_end/tool/benchmarker.dart index bc93a3366a8..01af037c8a6 100644 --- a/pkg/front_end/tool/benchmarker.dart +++ b/pkg/front_end/tool/benchmarker.dart @@ -49,12 +49,14 @@ void main(List args) { List>> runResults = []; List gcInfos = []; + Warnings warnings = new Warnings(); for (String snapshot in snapshots) { List> snapshotResults = []; runResults.add(snapshotResults); for (int iteration = 0; iteration < iterations; iteration++) { - Map benchmarkRun = - _benchmark(aotRuntime, core, snapshot, [], arguments); + Map benchmarkRun = _benchmark( + aotRuntime, core, snapshot, [], arguments, + warnings: warnings); if (checkFileSize != null) { File f = new File(checkFileSize); if (f.existsSync()) { @@ -79,6 +81,15 @@ void main(List args) { } printGcDiff(gcInfos.first, gcInfos[i]); } + + if (warnings.scalingInEffect) { + print("Be aware the the above was with scaling in effect."); + print("As such the results are likely useless."); + print("Possibly some other process is using the hardware counters."); + print("Running this tool"); + print("sudo out/ReleaseX64/dart pkg/front_end/tool/perf_event_tool.dart"); + print("will attempt to give you such information."); + } } void _help() { @@ -170,7 +181,7 @@ late final RegExp _extractNumbers = Map _benchmark(String aotRuntime, int core, String snapshot, List extraVmArguments, List arguments, - {bool silent = false}) { + {bool silent = false, Warnings? warnings}) { if (!silent) stdout.write("."); ProcessResult processResult = Process.runSync("perf", [ "stat", @@ -239,6 +250,7 @@ Map _benchmark(String aotRuntime, int core, String snapshot, result[caption] = value; if (scaling != null) { print("WARNING: $caption is scaled at $scaling!"); + warnings?.scalingInEffect = true; } } } @@ -369,3 +381,7 @@ class GCInfo { GCInfo(this.combinedTime, this.countWhat); } + +class Warnings { + bool scalingInEffect = false; +} diff --git a/pkg/front_end/tool/perf_event_tool.dart b/pkg/front_end/tool/perf_event_tool.dart new file mode 100644 index 00000000000..2c7fdcef69f --- /dev/null +++ b/pkg/front_end/tool/perf_event_tool.dart @@ -0,0 +1,74 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import "dart:io"; + +const bool debug = false; + +/// Tool to find and display any process using perf_events which as a +/// consequence might use one of the hardware counters, leaving fewer for +/// `perf stat` stuff. +/// Likely has to be run as root. +void main() { + try { + mainImpl(); + } catch (e) { + print("Got the error '$e'."); + print(""); + print("┌───────────────────────────────────────────────────┐"); + print("│ Note that this tool likely has to be run as root. │"); + print("└───────────────────────────────────────────────────┘"); + print(""); + rethrow; + } +} + +void mainImpl() { + if (!Platform.isLinux) { + throw "This tool only works in Linux."; + } + bool foundSomething = false; + Directory dir = new Directory("/proc/"); + for (FileSystemEntity pidDir in dir.listSync(recursive: false)) { + if (pidDir is! Directory) continue; + Uri pidUri = pidDir.uri; + String possiblePid = pidUri.pathSegments[pidUri.pathSegments.length - 2]; + int? candidatePid = int.tryParse(possiblePid); + if (candidatePid == null) continue; + Directory fdDir = new Directory.fromUri(pidDir.uri.resolve("fd/")); + int count = 0; + for (FileSystemEntity entry in fdDir.listSync()) { + if (debug) { + print("$entry"); + } + if (entry is Link) { + String target = entry.targetSync(); + if (debug) { + print(" => target: $target"); + } + if (target.contains("perf_event")) { + count++; + } + } + } + if (count > 0) { + print("Found $count perf event file descriptors for " + "process with pid $candidatePid:"); + runPsForPid(candidatePid); + print(""); + foundSomething = true; + } + } + + if (!foundSomething) { + print("Found no open perf file descriptors."); + return; + } +} + +void runPsForPid(int pid) { + ProcessResult psRun = Process.runSync("ps", ["-p", "$pid", "u"]); + stdout.write(psRun.stdout); + stderr.write(psRun.stderr); +}