mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 15:57:17 +00:00
606a64a743
- Flip flag to make strong null safety the default - Remove code that auto detects null safety mode from source files, it is necessary to specify --no-strong-null-safety to opt out. - Retains sniffing of AOT/JIT snapshots and kernel files to determine null safety mode, the opt out has to be done when generating these file. TEST=ci Change-Id: If2c9608eedb7c46d9c3cd85e261ee9640e0d28eb Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/261140 Reviewed-by: Alexander Thomas <athom@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com> Reviewed-by: Johnni Winther <johnniwinther@google.com> Commit-Queue: Siva Annamalai <asiva@google.com> Reviewed-by: Sigmund Cherem <sigmund@google.com>
110 lines
3.7 KiB
Dart
110 lines
3.7 KiB
Dart
// Copyright (c) 2014, 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.
|
|
//
|
|
// NOTE: See also wrapper script sdk/runtime/tools/bmu_benchmark_gallery.sh
|
|
//
|
|
// Tool to compute bounded mutator utilization (BMU) from a --verbose_gc log.
|
|
// Outputs CSV suitable for, e.g., gnuplot:
|
|
//
|
|
// dart --verbose_gc foo.dart 2> foo.gclog
|
|
// dart verbose_gc_to_bmu.dart < foo.gclog > foo.bmu
|
|
// gnuplot -p -e "set yr [0:1]; set logscale x; plot 'foo.bmu' with linespoints"
|
|
|
|
import 'dart:io';
|
|
import 'dart:math';
|
|
|
|
const WINDOW_STEP_FACTOR = 0.9;
|
|
const MINIMUM_WINDOW_SIZE_MS = 1;
|
|
|
|
class Interval {
|
|
int begin;
|
|
int end;
|
|
Interval(this.begin, this.end);
|
|
int get length => max(0, end - begin);
|
|
Interval overlap(Interval other) =>
|
|
new Interval(max(this.begin, other.begin), min(this.end, other.end));
|
|
}
|
|
|
|
class Timeline {
|
|
// Pauses must be added in non-decreasing order of 'begin'.
|
|
void addPause(Interval pause) {
|
|
var last = _pauses.isEmpty ? new Interval(0, 0) : _pauses.last;
|
|
assert(last.begin <= pause.begin);
|
|
// Trim any initial overlap.
|
|
_pauses.add(new Interval(max(pause.begin, last.end), pause.end));
|
|
// TODO(koda): Make VM log actual end time, rather than just last GC end.
|
|
_run.end = max(_run.end, pause.end);
|
|
}
|
|
|
|
int get maxWindowSize => _run.length;
|
|
|
|
// The windowSize must be no larger than the entire run.
|
|
double minUtilization(int windowSize) {
|
|
assert(windowSize <= _run.length);
|
|
// The minimum utilization can always be found in a window that has one of
|
|
// its endpoints at the beginning or end of a pause or the entire timeline.
|
|
List<int> interesting = [_run.begin, _run.end];
|
|
for (Interval p in _pauses) {
|
|
interesting.add(p.begin);
|
|
interesting.add(p.end);
|
|
}
|
|
double result = 1.0;
|
|
for (int i in interesting) {
|
|
result = min(result, _utilization(new Interval(i, i + windowSize)));
|
|
result = min(result, _utilization(new Interval(i - windowSize, i)));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
// Returns the fraction of non-pause time, or 1.0 for an invalid interval.
|
|
double _utilization(Interval iv) {
|
|
if (_run.begin > iv.begin || iv.end > _run.end || iv.length == 0) {
|
|
return 1.0;
|
|
}
|
|
int paused = 0;
|
|
for (Interval p in _pauses) {
|
|
paused += p.overlap(iv).length;
|
|
}
|
|
return 1.0 - (paused / iv.length);
|
|
}
|
|
|
|
final Interval _run = new Interval(0, 0);
|
|
final List<Interval> _pauses = [];
|
|
}
|
|
|
|
// Returns a GC pause as an interval in microseconds since program start, or
|
|
// the interval [0, 0) on parse error.
|
|
Interval parseVerboseGCLine(String line) {
|
|
var fields = line.split(',');
|
|
// Update this (and indices below, if needed) when logging format changes.
|
|
if (fields.length < 10) {
|
|
// Ignore the lines that just specify column names, separated by '|'.
|
|
// We assume these have very few commas in them, so that fields.length
|
|
// is < 10.
|
|
assert(line.contains("|"));
|
|
return new Interval(0, 0);
|
|
}
|
|
var begin = (1e6 * double.parse(fields[2])).floor();
|
|
var duration = (1000 * double.parse(fields[3])).floor();
|
|
var end = begin + duration;
|
|
return new Interval(begin, end);
|
|
}
|
|
|
|
void main() {
|
|
Timeline t = new Timeline();
|
|
for (String? line = stdin.readLineSync();
|
|
line != null;
|
|
line = stdin.readLineSync()) {
|
|
t.addPause(parseVerboseGCLine(line));
|
|
}
|
|
print('# window_size_ms, bounded_mutator_utilization');
|
|
var minimumSeen = 1.0;
|
|
for (int w = t._run.length;
|
|
w > 1000 * MINIMUM_WINDOW_SIZE_MS;
|
|
w = (w * WINDOW_STEP_FACTOR).floor()) {
|
|
minimumSeen = min(minimumSeen, t.minUtilization(w));
|
|
print('${w / 1000}, $minimumSeen');
|
|
}
|
|
}
|