Skip to content

Commit 5f198ae

Browse files
aamcommit-bot@chromium.org
authored andcommitted
[vm/benchmarks] Add IsolateSpawn spawn latency and memory benchmarks.
The benchmark spawns an isolate that compiles hello world app with dart2js, measures time it takes for spawned isolate to get up and running, measures delta rss when isolate is spawned. This also adds analysis_options.yaml that helps with keeping the code lint-free. Change-Id: I5f1ffa9706766cd00bf1ea3fdad76957952de8a1 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/119538 Reviewed-by: Jonas Termansen <[email protected]> Commit-Queue: Alexander Aprelev <[email protected]>
1 parent a9e1e7e commit 5f198ae

File tree

4 files changed

+272
-0
lines changed

4 files changed

+272
-0
lines changed
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
// Copyright (c) 2019, 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:async';
6+
import 'dart:io';
7+
import 'dart:isolate';
8+
import 'dart:math';
9+
10+
import 'package:meta/meta.dart';
11+
12+
import 'package:compiler/src/dart2js.dart' as dart2js_main;
13+
14+
class SpawnLatencyAndMemory {
15+
SpawnLatencyAndMemory(this.name);
16+
17+
Future<ResultMessageLatencyAndMemory> run() async {
18+
final completerResult = Completer();
19+
final receivePort = ReceivePort()..listen(completerResult.complete);
20+
final Completer<DateTime> isolateExitedCompleter = Completer<DateTime>();
21+
final onExitReceivePort = ReceivePort()
22+
..listen((_) {
23+
isolateExitedCompleter.complete(DateTime.now());
24+
});
25+
final DateTime beforeSpawn = DateTime.now();
26+
await Isolate.spawn(
27+
isolateCompiler,
28+
StartMessageLatencyAndMemory(
29+
receivePort.sendPort, beforeSpawn, ProcessInfo.currentRss),
30+
onExit: onExitReceivePort.sendPort,
31+
onError: onExitReceivePort.sendPort);
32+
final DateTime afterSpawn = DateTime.now();
33+
34+
final ResultMessageLatencyAndMemory result = await completerResult.future;
35+
receivePort.close();
36+
final DateTime isolateExited = await isolateExitedCompleter.future;
37+
result.timeToExitUs = isolateExited.difference(beforeSpawn).inMicroseconds;
38+
result.timeToIsolateSpawnUs =
39+
afterSpawn.difference(beforeSpawn).inMicroseconds;
40+
onExitReceivePort.close();
41+
42+
return result;
43+
}
44+
45+
Future<AggregatedResultMessageLatencyAndMemory> measureFor(
46+
int minimumMillis) async {
47+
final minimumMicros = minimumMillis * 1000;
48+
final watch = Stopwatch()..start();
49+
final Metric toAfterIsolateSpawnUs = LatencyMetric("${name}ToAfterSpawn");
50+
final Metric toStartRunningCodeUs = LatencyMetric("${name}ToStartRunning");
51+
final Metric toFinishRunningCodeUs =
52+
LatencyMetric("${name}ToFinishRunning");
53+
final Metric toExitUs = LatencyMetric("${name}ToExit");
54+
final Metric deltaRss = MemoryMetric("${name}Delta");
55+
while (watch.elapsedMicroseconds < minimumMicros) {
56+
final ResultMessageLatencyAndMemory result = await run();
57+
toAfterIsolateSpawnUs.add(result.timeToIsolateSpawnUs);
58+
toStartRunningCodeUs.add(result.timeToStartRunningCodeUs);
59+
toFinishRunningCodeUs.add(result.timeToFinishRunningCodeUs);
60+
toExitUs.add(result.timeToExitUs);
61+
deltaRss.add(result.deltaRss);
62+
}
63+
return AggregatedResultMessageLatencyAndMemory(toAfterIsolateSpawnUs,
64+
toStartRunningCodeUs, toFinishRunningCodeUs, toExitUs, deltaRss);
65+
}
66+
67+
Future<AggregatedResultMessageLatencyAndMemory> measure() async {
68+
await measureFor(500); // warm-up
69+
return measureFor(4000); // actual measurement
70+
}
71+
72+
Future<void> report() async {
73+
final AggregatedResultMessageLatencyAndMemory result = await measure();
74+
print(result);
75+
}
76+
77+
final String name;
78+
RawReceivePort receivePort;
79+
}
80+
81+
class Metric {
82+
Metric({@required this.prefix, @required this.suffix});
83+
84+
void add(int value) {
85+
if (value > max) {
86+
max = value;
87+
}
88+
sum += value;
89+
sumOfSquares += value * value;
90+
count++;
91+
}
92+
93+
double _average() => sum / count;
94+
double _rms() => sqrt(sumOfSquares / count);
95+
96+
toString() => "$prefix): ${_average()}$suffix\n"
97+
"${prefix}Max): $max$suffix\n"
98+
"${prefix}RMS): ${_rms()}$suffix";
99+
100+
final String prefix;
101+
final String suffix;
102+
int max = 0;
103+
double sum = 0;
104+
double sumOfSquares = 0;
105+
int count = 0;
106+
}
107+
108+
class LatencyMetric extends Metric {
109+
LatencyMetric(String name) : super(prefix: "${name}(Latency", suffix: " us.");
110+
}
111+
112+
class MemoryMetric extends Metric {
113+
MemoryMetric(String name) : super(prefix: "${name}Rss(MemoryUse", suffix: "");
114+
115+
toString() => "$prefix): ${_average()}$suffix\n";
116+
}
117+
118+
class StartMessageLatencyAndMemory {
119+
StartMessageLatencyAndMemory(this.sendPort, this.spawned, this.rss);
120+
121+
final SendPort sendPort;
122+
final DateTime spawned;
123+
final int rss;
124+
}
125+
126+
class ResultMessageLatencyAndMemory {
127+
ResultMessageLatencyAndMemory(
128+
{this.timeToStartRunningCodeUs,
129+
this.timeToFinishRunningCodeUs,
130+
this.deltaRss});
131+
132+
final int timeToStartRunningCodeUs;
133+
final int timeToFinishRunningCodeUs;
134+
final int deltaRss;
135+
136+
int timeToIsolateSpawnUs;
137+
int timeToExitUs;
138+
}
139+
140+
class AggregatedResultMessageLatencyAndMemory {
141+
AggregatedResultMessageLatencyAndMemory(
142+
this.toAfterIsolateSpawnUs,
143+
this.toStartRunningCodeUs,
144+
this.toFinishRunningCodeUs,
145+
this.toExitUs,
146+
this.deltaRss,
147+
);
148+
149+
String toString() => """$toAfterIsolateSpawnUs
150+
$toStartRunningCodeUs
151+
$toFinishRunningCodeUs
152+
$toExitUs
153+
$deltaRss""";
154+
155+
final Metric toAfterIsolateSpawnUs;
156+
final Metric toStartRunningCodeUs;
157+
final Metric toFinishRunningCodeUs;
158+
final Metric toExitUs;
159+
final Metric deltaRss;
160+
}
161+
162+
Future<void> isolateCompiler(StartMessageLatencyAndMemory start) async {
163+
final DateTime timeRunningCodeUs = DateTime.now();
164+
await runZoned(
165+
() => dart2js_main.internalMain(<String>[
166+
"benchmarks/IsolateSpawn/dart/helloworld.dart",
167+
'--libraries-spec=sdk/lib/libraries.json'
168+
]),
169+
zoneSpecification: ZoneSpecification(
170+
print: (Zone self, ZoneDelegate parent, Zone zone, String line) {}));
171+
final DateTime timeFinishRunningCodeUs = DateTime.now();
172+
start.sendPort.send(ResultMessageLatencyAndMemory(
173+
timeToStartRunningCodeUs:
174+
timeRunningCodeUs.difference(start.spawned).inMicroseconds,
175+
timeToFinishRunningCodeUs:
176+
timeFinishRunningCodeUs.difference(start.spawned).inMicroseconds,
177+
deltaRss: ProcessInfo.currentRss - start.rss));
178+
}
179+
180+
Future<void> main() async {
181+
await SpawnLatencyAndMemory("IsolateSpawn.Dart2JS").report();
182+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
main() {
2+
print('Hello, world!');
3+
}

benchmarks/analysis_options.yaml

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
include: package:pedantic/analysis_options.yaml
2+
#analyzer:
3+
# strong-mode:
4+
# implicit-casts: false
5+
linter:
6+
rules:
7+
#- always_declare_return_types
8+
#- annotate_overrides
9+
- avoid_empty_else
10+
- avoid_function_literals_in_foreach_calls
11+
- avoid_init_to_null
12+
- avoid_null_checks_in_equality_operators
13+
- avoid_relative_lib_imports
14+
- avoid_renaming_method_parameters
15+
- avoid_return_types_on_setters
16+
- avoid_returning_null
17+
- avoid_returning_null_for_future
18+
- avoid_shadowing_type_parameters
19+
- avoid_types_as_parameter_names
20+
- avoid_unused_constructor_parameters
21+
- await_only_futures
22+
- camel_case_types
23+
- cancel_subscriptions
24+
- comment_references
25+
#- constant_identifier_names
26+
- control_flow_in_finally
27+
- directives_ordering
28+
- empty_catches
29+
- empty_constructor_bodies
30+
- empty_statements
31+
- hash_and_equals
32+
- implementation_imports
33+
- invariant_booleans
34+
- iterable_contains_unrelated_type
35+
- library_names
36+
- library_prefixes
37+
- list_remove_unrelated_type
38+
- literal_only_boolean_expressions
39+
- no_adjacent_strings_in_list
40+
- no_duplicate_case_values
41+
#- non_constant_identifier_names
42+
- null_closures
43+
#- omit_local_variable_types
44+
#- only_throw_errors
45+
- overridden_fields
46+
- package_api_docs
47+
- package_names
48+
- package_prefixed_library_names
49+
- prefer_adjacent_string_concatenation
50+
- prefer_collection_literals
51+
- prefer_conditional_assignment
52+
- prefer_const_constructors
53+
- prefer_contains
54+
- prefer_equal_for_default_values
55+
- prefer_generic_function_type_aliases
56+
- prefer_final_fields
57+
- prefer_final_locals
58+
- prefer_initializing_formals
59+
- prefer_interpolation_to_compose_strings
60+
- prefer_is_empty
61+
- prefer_is_not_empty
62+
#- prefer_single_quotes
63+
#- prefer_typing_uninitialized_variables
64+
- recursive_getters
65+
- slash_for_doc_comments
66+
- test_types_in_equals
67+
- throw_in_finally
68+
- type_init_formals
69+
- unawaited_futures
70+
- unnecessary_await_in_return
71+
- unnecessary_brace_in_string_interps
72+
- unnecessary_const
73+
- unnecessary_getters_setters
74+
- unnecessary_lambdas
75+
- unnecessary_new
76+
- unnecessary_null_aware_assignments
77+
- unnecessary_parenthesis
78+
- unnecessary_statements
79+
#- unnecessary_this
80+
- unrelated_type_equality_checks
81+
- use_function_type_syntax_for_parameters
82+
- use_rethrow_when_possible
83+
- valid_regexps

tools/bots/try_benchmarks.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ for command; do
8989
-- \
9090
third_party/d8/linux/ia32/natives_blob.bin \
9191
third_party/d8/linux/ia32/snapshot_blob.bin \
92+
out/ReleaseIA32/dart2js_platform.dill \
9293
out/ReleaseIA32/vm_outline_strong.dill \
9394
out/ReleaseIA32/vm_platform_strong.dill \
9495
out/ReleaseIA32/gen/kernel_service.dill \
@@ -174,6 +175,7 @@ for command; do
174175
-- \
175176
third_party/d8/linux/ia32/natives_blob.bin \
176177
third_party/d8/linux/ia32/snapshot_blob.bin \
178+
out/ReleaseIA32/dart2js_platform.dill \
177179
out/ReleaseIA32/vm_outline_strong.dill \
178180
out/ReleaseIA32/vm_platform_strong.dill \
179181
out/ReleaseIA32/gen/kernel_service.dill \
@@ -254,6 +256,7 @@ EOF
254256
-- \
255257
third_party/d8/linux/x64/natives_blob.bin \
256258
third_party/d8/linux/x64/snapshot_blob.bin \
259+
out/ReleaseX64/dart2js_platform.dill \
257260
out/ReleaseX64/vm_outline_strong.dill \
258261
out/ReleaseX64/vm_platform_strong.dill \
259262
out/ReleaseX64/gen/kernel_service.dill \
@@ -358,6 +361,7 @@ EOF
358361
-- \
359362
third_party/d8/linux/x64/natives_blob.bin \
360363
third_party/d8/linux/x64/snapshot_blob.bin \
364+
out/ReleaseX64/dart2js_platform.dill \
361365
out/ReleaseX64/vm_outline_strong.dill \
362366
out/ReleaseX64/vm_platform_strong.dill \
363367
out/ReleaseX64/gen/kernel_service.dill \

0 commit comments

Comments
 (0)