Skip to content

Commit e5c2dd2

Browse files
jensjohaCommit Queue
authored andcommitted
[CFE] Allow counting method calls when instrumenting
When instrumenting one can use "--count" to instrument counting method calls instead of instrumenting to create a flame graph. From that I can for instance see that `Reference.node` is called 6+ mio times when compiling compile.dart. Example run: out/ReleaseX64/dart pkg/front_end/tool/flame/instrumenter.dart pkg/front_end/tool/_fasta/compile.dart --count out/ReleaseX64/dart pkg/front_end/tool/_fasta/compile.dart.dill.instrumented.dill pkg/front_end/tool/_fasta/compile.dart Change-Id: I583f4b53a474c3777bb059ea89d932607b7c23ad Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/298100 Reviewed-by: Johnni Winther <[email protected]> Commit-Queue: Jens Johansen <[email protected]>
1 parent 1574e86 commit e5c2dd2

File tree

2 files changed

+92
-7
lines changed

2 files changed

+92
-7
lines changed

pkg/front_end/tool/flame/instrumenter.dart

100755100644
Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,11 @@ Future<void> main(List<String> arguments) async {
2626
Future<void> _main(List<String> inputArguments, Directory tmpDir) async {
2727
List<String> candidates = [];
2828
List<String> arguments = [];
29+
bool doCount = false;
2930
for (String arg in inputArguments) {
30-
if (arg.startsWith("--candidates=")) {
31+
if (arg == "--count") {
32+
doCount = true;
33+
} else if (arg.startsWith("--candidates=")) {
3134
candidates.add(arg.substring("--candidates=".length));
3235
} else {
3336
arguments.add(arg);
@@ -46,10 +49,14 @@ Future<void> _main(List<String> inputArguments, Directory tmpDir) async {
4649

4750
print("Compiling the instrumentation library.");
4851
Uri instrumentationLibDill = tmpDir.uri.resolve("instrumenter.dill");
52+
String libFilename = "instrumenter_lib.dart";
53+
if (doCount) {
54+
libFilename = "instrumenter_lib_counter.dart";
55+
}
4956
await fasta_compile.main([
5057
"--omit-platform",
5158
"-o=${instrumentationLibDill.toFilePath()}",
52-
Platform.script.resolve("instrumenter_lib.dart").toFilePath()
59+
Platform.script.resolve(libFilename).toFilePath()
5360
]);
5461
if (!File.fromUri(instrumentationLibDill).existsSync()) {
5562
throw "Instrumentation library didn't compile as expected.";
@@ -117,11 +124,15 @@ void addIfWanted(List<Procedure> output, List<Procedure> input,
117124
}
118125
}
119126

120-
String getName(Procedure p) {
127+
String getName(Procedure p, {bool renameSetter = false}) {
128+
String name = p.name.text;
129+
if (renameSetter && p.isSetter) {
130+
name = "set:$name";
131+
}
121132
if (p.parent is Class) {
122-
return "${(p.parent as Class).name}.${p.name.text}";
133+
return "${(p.parent as Class).name}.$name";
123134
} else {
124-
return p.name.text;
135+
return name;
125136
}
126137
}
127138

@@ -162,8 +173,9 @@ void initializeAndReport(
162173
instrumenterReport,
163174
new Arguments([
164175
new ListLiteral(procedures
165-
.map((p) => new StringLiteral(
166-
"${p.fileUri.pathSegments.last}|${getName(p)}"))
176+
.map(
177+
(p) => new StringLiteral("${p.fileUri.pathSegments.last}|"
178+
"${getName(p, renameSetter: true)}"))
167179
.toList()),
168180
new BoolLiteral(reportCandidates),
169181
])))),
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import "dart:typed_data";
6+
7+
Stopwatch stopwatch = new Stopwatch();
8+
9+
Uint32List counts = new Uint32List(0);
10+
11+
void initialize(int count) {
12+
counts = new Uint32List(count);
13+
stopwatch.start();
14+
}
15+
16+
@pragma("vm:prefer-inline")
17+
void enter(int i) {
18+
counts[i]++;
19+
}
20+
21+
@pragma("vm:prefer-inline")
22+
void exit(int i) {}
23+
24+
void report(List<String> names, bool reportCandidates) {
25+
List<NameWithCount> data = [];
26+
for (int i = 0; i < counts.length; i++) {
27+
int count = counts[i];
28+
if (count < 10000) continue;
29+
data.add(new NameWithCount(names[i], count));
30+
}
31+
data.sort((a, b) => a.count - b.count);
32+
for (NameWithCount element in data) {
33+
print("${_formatInt(element.count, 11)}: ${element.name}");
34+
}
35+
}
36+
37+
class NameWithCount {
38+
final String name;
39+
final int count;
40+
41+
NameWithCount(this.name, this.count);
42+
}
43+
44+
String _formatInt(int input, int minLength) {
45+
bool negative = false;
46+
if (input < 0) {
47+
negative = true;
48+
input = -input;
49+
}
50+
String asString = "$input";
51+
int length = asString.length;
52+
int countSeparators = (length - 1) ~/ 3;
53+
int outLength = length + countSeparators;
54+
if (negative) outLength++;
55+
StringBuffer sb = new StringBuffer();
56+
if (outLength < minLength) {
57+
sb.write(" " * (minLength - outLength));
58+
}
59+
60+
if (negative) sb.write("-");
61+
int end = length - (countSeparators * 3);
62+
sb.write(asString.substring(0, end));
63+
int begin = end;
64+
end += 3;
65+
while (end <= length) {
66+
sb.write(",");
67+
sb.write(asString.substring(begin, end));
68+
begin = end;
69+
end += 3;
70+
}
71+
72+
return sb.toString();
73+
}

0 commit comments

Comments
 (0)