Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(334)

Unified Diff: sdk/lib/_internal/compiler/implementation/helpers/stats.dart

Issue 694353007: Move dart2js from sdk/lib/_internal/compiler to pkg/compiler (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: sdk/lib/_internal/compiler/implementation/helpers/stats.dart
diff --git a/sdk/lib/_internal/compiler/implementation/helpers/stats.dart b/sdk/lib/_internal/compiler/implementation/helpers/stats.dart
deleted file mode 100644
index 13897c72c46425d72160ed48b7f3e8b142204ce1..0000000000000000000000000000000000000000
--- a/sdk/lib/_internal/compiler/implementation/helpers/stats.dart
+++ /dev/null
@@ -1,788 +0,0 @@
-// 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.
-
-part of dart2js.helpers;
-
-// Helper methods for statistics.
-
-/// Current stats collector. Use [enableStatsOutput] to enable recording of
-/// stats.
-Stats get stats {
- enableDebugMode();
- if (_stats == null) {
- _stats = const Stats();
- }
- return _stats;
-}
-
-Stats _stats;
-
-/// Enable recording of stats. Use [Stats.dumpStats] to output the record stats.
-///
-/// Pass the [outputProvider] of [Compiler] to generate stats into a separate
-/// file using [name] and [extension] for the filename. If omitted, stats are
-/// printed on standard out.
-///
-/// If [xml] is `true`, stats output is formatted as XML with a default
-/// extension of 'xml', otherwise the output is indented text with a default
-/// extension of 'log'.
-void enableStatsOutput({CompilerOutputProvider outputProvider,
- bool xml: true,
- String name: 'stats',
- String extension,
- int examples: 10}) {
- if (_stats != null) {
- throw new StateError('Stats have already been initialized.');
- }
- enableDebugMode();
-
- StatsOutput output;
- if (outputProvider != null) {
- if (extension == null) {
- extension = xml ? 'xml' : 'log';
- }
- output = new SinkOutput(outputProvider(name, extension));
- } else {
- output = const DebugOutput();
- }
- StatsPrinter printer;
- if (xml) {
- printer = new XMLPrinter(output: output, examples: examples);
- } else {
- printer = new ConsolePrinter(output: output, examples: examples);
- }
- _stats = new ActiveStats(printer);
-}
-
-/// Interface for gathering and display of statistical information.
-/// This class serves as the noop collector.
-class Stats {
- const Stats();
-
- /// Registers [key], [value] pair in the map [id]. If [fromExisting] is
- /// non-null and [key] already exists, the value associated with [key] will
- /// be the return value of [fromExisting] when called with the existing value.
- ///
- /// The recorded information is not dumped automatically.
- void recordMap(id, key, value, {fromExisting(value)}) {}
-
- /// Returns the map [id] recorded with [recordMap].
- Map getMap(id) => const {};
-
- /// Registers [element] as an element of the list [id]. If provided, [data]
- /// provides additional data for [element].
- ///
- /// The recorded information is dumped automatically on call to [dumpStats].
- ///
- /// Example:
- /// Calling [recordElement] like this:
- /// recordElement('foo', 'a', data: 'first-a-data');
- /// recordElement('foo', 'a', data: 'second-a-data');
- /// recordElement('foo', 'b');
- /// recordElement('bar', 'a', data: 'third-a-data');
- /// recordElement('bar', 'c');
- /// will result in a dump like this:
- /// foo: 2
- /// value=a data=second-a-data
- /// b
- /// bar: 2
- /// value=a data=third-a-data
- /// c
- ///
- void recordElement(id, element, {data}) {}
-
- /// Returns the list [id] recorded with [recordElement].
- Iterable getList(String id) => const [];
-
- /// Registers [value] as an occurrence of [id]. If passed, [example] provides
- /// an example data of the occurrence of [value].
- ///
- /// The recorded information is dumped automatically on call to [dumpStats].
- ///
- /// Example:
- /// Calling [recordFrequency] like this:
- /// recordFrequency('foo', 'a', 'first-a-data');
- /// recordFrequency('foo', 'a', 'second-a-data');
- /// recordFrequency('bar', 'b', 'first-b-data');
- /// recordFrequency('foo', 'c');
- /// recordFrequency('bar', 'b');
- /// will result in a dump like this:
- /// foo:
- /// a: 2
- /// first-a-data
- /// second-a-data
- /// c: 1
- /// bar:
- /// b: 2
- /// first-b-data
- ///
- void recordFrequency(id, value, [example]) {}
-
- /// For each key/value pair in [map] the elements in the value are registered
- /// as examples of occurrences of the key in [id].
- void recordFrequencies(id, Map<dynamic, Iterable> map) {}
-
- /// Returns the examples given for the occurrence of [value] for [id].
- Iterable recordedFrequencies(id, value) => const [];
-
- /// Increases the counter [id] by 1. If provided, [example] is used as an
- /// example of the count and [data] provides additional information for
- /// [example].
- ///
- /// The recorded information is dumped automatically on call to [dumpStats].
- ///
- /// Example:
- /// Calling [recordCounter] like this:
- /// recordCounter('foo', 'a');
- /// recordCounter('foo', 'a');
- /// recordCounter('foo', 'b');
- /// recordCounter('bar', 'c', 'first-c-data');
- /// recordCounter('bar', 'c', 'second-c-data');
- /// recordCounter('bar', 'd');
- /// recordCounter('bar', 'd');
- /// recordCounter('baz');
- /// recordCounter('baz');
- /// will result in a dump like this:
- /// foo: 3
- /// count=2 example=a
- /// count=1 example=b
- /// bar: 4
- /// count=2 examples=2
- /// c:
- /// first-c-data
- /// second-c-data
- /// d
- /// baz: 2
- ///
- void recordCounter(id, [example, data]) {}
-
- /// Records the current stack trace under the key [id]. Only every
- /// [sampleFrequency] call with the same id is recorded, and if omitted
- /// [stackTraceSampleFrequency] is used.
- void recordTrace(id, {int sampleFrequency}) {}
-
- /// The default sample frequency used for recording stack traces.
- int get stackTraceSampleFrequency => 0;
-
- /// Set the default sample frequency used for recording stack traces.
- void set stackTraceSampleFrequency(int value) {}
-
- /// Dumps the stats for the recorded frequencies, sets, and counters. If
- /// provided [beforeClose] is called before closing the dump output. This
- /// can be used to include correlations on the collected data through
- /// [dumpCorrelation].
- void dumpStats({void beforeClose()}) {}
-
- /// Prints the correlation between the elements of [a] and [b].
- ///
- /// Three sets are output using [idA] and [idB] as labels for the elements
- /// [a] and [b]:
- ///
- /// 'idA && idB' lists the elements both in [a] and [b],
- /// '!idA && idB' lists the elements not in [a] but in [b], and
- /// 'idA && !idB' lists the elements in [a] but not in [b].
- ///
- /// If [dataA] and/or [dataB] are provided, additional information on the
- /// elements are looked up in [dataA] or [dataB] using [dataA] as the primary
- /// source.
- void dumpCorrelation(idA, Iterable a, idB, Iterable b,
- {Map dataA, Map dataB}) {}
-}
-
-/// Interface for printing output data.
-///
-/// This class serves as the disabled output.
-class StatsOutput {
- const StatsOutput();
-
- /// Print [text] as on a separate line.
- void println(String text) {}
-}
-
-/// Output to the [debugPrint] method.
-class DebugOutput implements StatsOutput {
- const DebugOutput();
-
- void println(String text) => debugPrint(text);
-}
-
-/// Output to an [EventSink]. Used to output to a file through the
-/// [CompilerOutputProvider].
-class SinkOutput implements StatsOutput {
- EventSink<String> sink;
-
- SinkOutput(this.sink);
-
- void println(String text) {
- sink.add(text);
- sink.add('\n');
- }
-}
-
-/// Interface for printing stats collected in [Stats].
-abstract class StatsPrinter {
- /// The number of examples printer. If `null` all examples are printed.
- int get examples => 0;
-
- /// Start a group [id].
- void start(String id) {}
-
- /// Create a group [id] with content created by [createGroupContent].
- void group(String id, void createGroupContent()) {
- start(id);
- createGroupContent();
- end(id);
- }
-
- /// End a group [id].
- void end(String id) {}
-
- /// Start a stat entry for [id] with additional [data].
- void open(String id,
- [Map<String, dynamic> data = const <String, dynamic>{}]) {}
-
- /// Create a stat entry for [id] with additional [data] and content created by
- /// [createChildContent].
- void child(String id,
- [Map<String, dynamic> data = const <String, dynamic>{},
- void createChildContent()]) {
- open(id, data);
- if (createChildContent != null) createChildContent();
- close(id);
- }
-
- /// End a stat entry for [id].
- void close(String id) {}
-
- /// Starts a group of additional information.
- void beginExtra() {}
-
- /// Starts a group of additional information.
- void endExtra() {}
-}
-
-/// Abstract base class for [ConsolePrinter] and [XMLPrinter].
-abstract class BasePrinter extends StatsPrinter with Indentation {
- final int examples;
- final StatsOutput output;
-
- BasePrinter({this.output: const DebugOutput(),
- this.examples: 10}) {
- indentationUnit = " ";
- }
-}
-
-/// [StatsPrinter] that displays stats in console lines.
-class ConsolePrinter extends BasePrinter {
- int extraLevel = 0;
-
- ConsolePrinter({StatsOutput output: const DebugOutput(),
- int examples: 10})
- : super(output: output, examples: examples);
-
- void open(String id,
- [Map<String, dynamic> data = const <String, dynamic>{}]) {
- if (extraLevel > 0) return;
-
- StringBuffer sb = new StringBuffer();
- sb.write(indentation);
- String space = '';
- if (data['title'] != null) {
- sb.write('${data['title']}:');
- space = ' ';
- data.remove('title');
- } else if (data['name'] != null) {
- sb.write('${data['name']}');
- space = ' ';
- data.remove('name');
- }
- Iterable nonNullValues = data.values.where((v) => v != null);
- if (nonNullValues.length == 1) {
- sb.write('$space${nonNullValues.first}');
- } else {
- data.forEach((key, value) {
- sb.write('$space$key=$value');
- space = ' ';
- });
- }
- output.println(sb.toString());
- indentMore();
- }
-
- void close(String id) {
- if (extraLevel > 0) return;
-
- indentLess();
- }
-
- void beginExtra() {
- if (extraLevel == 0) output.println('$indentation...');
- extraLevel++;
- }
-
- void endExtra() {
- extraLevel--;
- }
-}
-
-/// [StatsPrinter] that displays stats in XML format.
-class XMLPrinter extends BasePrinter {
- static const HtmlEscape escape = const HtmlEscape();
- bool opened = false;
-
- XMLPrinter({output: const DebugOutput(),
- int examples: 10})
- : super(output: output, examples: examples);
-
- void start(String id) {
- if (!opened) {
- output.println('<?xml version="1.0" encoding="UTF-8"?>');
- opened = true;
- }
- open(id);
- }
-
- void end(String id) {
- close(id);
- }
-
- void open(String id,
- [Map<String, dynamic> data = const <String, dynamic>{}]) {
- StringBuffer sb = new StringBuffer();
- sb.write(indentation);
- sb.write('<$id');
- data.forEach((key, value) {
- if (value != null) {
- sb.write(' $key="${escape.convert('$value')}"');
- }
- });
- sb.write('>');
- output.println(sb.toString());
- indentMore();
- }
-
- void close(String id) {
- indentLess();
- output.println('${indentation}</$id>');
- }
-
- void beginExtra() {
- open('extra');
- }
-
- void endExtra() {
- close('extra');
- }
-}
-
-/// A node in a stack trace tree used to store and organize stack traces by
-/// common prefixes.
-class _StackTraceNode implements Comparable<_StackTraceNode> {
- int count;
- List<StackTraceLine> commonPrefix;
- List<_StackTraceNode> subtraces;
-
- _StackTraceNode(this.commonPrefix, this.count, this.subtraces);
-
- _StackTraceNode.root() : this([], 0, []);
-
- _StackTraceNode.leaf(StackTraceLines stackTrace)
- : this(stackTrace.lines, 1, const []);
-
- _StackTraceNode.node(List<StackTraceLine> commonPrefix,
- _StackTraceNode first,
- _StackTraceNode second)
- : this(commonPrefix, first.count + second.count, [first, second]);
-
- void add(StackTraceLines stackTrace) {
- count++;
- if (!stackTrace.lines.isEmpty) {
- addSubtrace(stackTrace);
- }
- }
-
- void addSubtrace(StackTraceLines stackTrace) {
- List<StackTraceLine> lines = stackTrace.lines;
- for (_StackTraceNode subtrace in subtraces) {
- int commonPrefixLength =
- longestCommonPrefixLength(subtrace.commonPrefix, lines);
- if (commonPrefixLength > 0) {
- stackTrace = stackTrace.subtrace(commonPrefixLength);
- if (commonPrefixLength == subtrace.commonPrefix.length) {
- subtrace.add(stackTrace);
- } else {
- subtrace.commonPrefix =
- subtrace.commonPrefix.sublist(commonPrefixLength);
- subtraces.remove(subtrace);
- subtraces.add(new _StackTraceNode.node(
- lines.sublist(0, commonPrefixLength),
- subtrace,
- new _StackTraceNode.leaf(stackTrace)));
- }
- return;
- }
- }
- subtraces.add(new _StackTraceNode.leaf(stackTrace));
- }
-
- void dumpTraces(StatsPrinter printer) {
- printer.open('trace', {'count': count, 'line': commonPrefix.first});
- if (commonPrefix.length > 1) {
- for (StackTraceLine line in commonPrefix.skip(1)) {
- printer.child('trace', {'line': line});
- }
- }
- dumpSubtraces(printer);
- printer.close('trace');
- }
-
- void dumpSubtraces(StatsPrinter printer) {
- if (!subtraces.isEmpty) {
- subtraces.sort();
- for (_StackTraceNode step in subtraces) {
- step.dumpTraces(printer);
- }
- }
- }
-
- int compareTo(_StackTraceNode other) {
- // Sorts in decreasing count order.
- return other.count - count;
- }
-
- void printOn(StringBuffer sb, String indentation) {
- String countText = '$indentation$count ';
- sb.write(countText);
- sb.write('\n');
- indentation = ''.padLeft(countText.length, ' ');
- if (commonPrefix != null) {
- int index = 0;
- for (String line in commonPrefix) {
- sb.write(indentation);
- if (index > 1) {
- sb.write('...\n');
- break;
- }
- sb.write(line);
- sb.write('\n');
- index++;
- }
- }
- subtraces.sort();
- for (_StackTraceNode subtrace in subtraces) {
- subtrace.printOn(sb, indentation);
- }
- }
-
- String toString() {
- StringBuffer sb = new StringBuffer();
- printOn(sb, '');
- return sb.toString();
- }
-}
-
-class _StackTraceTree extends _StackTraceNode {
- final id;
- int totalCount = 0;
- final int sampleFrequency;
-
- _StackTraceTree(this.id, this.sampleFrequency) : super.root();
-
- void dumpTraces(StatsPrinter printer) {
- printer.open('trace', {
- 'id': id,
- 'totalCount': totalCount,
- 'sampleFrequency': sampleFrequency});
- dumpSubtraces(printer);
- printer.close('trace');
- }
-
- void sample() {
- if (totalCount++ % sampleFrequency == 0) {
- add(stackTrace(offset: 3));
- }
- }
-}
-
-/// Actual implementation of [Stats].
-class ActiveStats implements Stats {
- final StatsPrinter printer;
- Map<dynamic, Map> maps = {};
- Map<dynamic, Map<dynamic, List>> frequencyMaps = {};
- Map<dynamic, Map> setsMap = {};
- Map<dynamic, Map<dynamic, List>> countersMap =
- <dynamic, Map<dynamic, List>>{};
- Map<dynamic, _StackTraceTree> traceMap = {};
- int stackTraceSampleFrequency = 1;
-
- ActiveStats(StatsPrinter this.printer);
-
- void recordMap(id, key, value, {fromExisting(value)}) {
- Map map = maps.putIfAbsent(id, () => {});
- if (fromExisting != null && map.containsKey(key)) {
- map[key] = fromExisting(map[key]);
- } else {
- map[key] = value;
- }
- }
-
- Map getMap(key) {
- return maps[key];
- }
-
- void recordFrequency(id, value, [example]) {
- Map<int, List> map = frequencyMaps.putIfAbsent(id, () => {});
- map.putIfAbsent(value, () => []);
- map[value].add(example);
- }
-
- void recordFrequencies(id, Map<dynamic, Iterable> frequencyMap) {
- Map<int, List> map = frequencyMaps.putIfAbsent(id, () => {});
- frequencyMap.forEach((value, examples) {
- map.putIfAbsent(value, () => []);
- map[value].addAll(examples);
- });
- }
-
- Iterable recordedFrequencies(id, value) {
- Map<dynamic, List> map = frequencyMaps[id];
- if (map == null) return const [];
- List list = map[value];
- if (list == null) return const [];
- return list;
- }
-
- void recordCounter(id, [reason, example]) {
- Map<dynamic, List> map = countersMap.putIfAbsent(id, () => {});
- map.putIfAbsent(reason, () => []).add(example);
- }
-
- void recordElement(key, element, {data}) {
- setsMap.putIfAbsent(key, () => new Map())[element] = data;
- }
-
- void recordTrace(key, {int sampleFrequency}) {
- if (sampleFrequency == null) {
- sampleFrequency = stackTraceSampleFrequency;
- }
- traceMap.putIfAbsent(key,
- () => new _StackTraceTree(key, sampleFrequency)).sample();
-
- }
-
- Iterable getList(String key) {
- Map map = setsMap[key];
- if (map == null) return const [];
- return map.keys;
- }
-
- void dumpStats({void beforeClose()}) {
- printer.start('stats');
- dumpFrequencies();
- dumpSets();
- dumpCounters();
- dumpTraces();
- if (beforeClose != null) {
- beforeClose();
- }
- printer.end('stats');
- }
-
- void dumpSets() {
- printer.group('sets', () {
- setsMap.forEach((k, set) {
- dumpIterable('examples', '$k', set.keys,
- limit: printer.examples, dataMap: set);
- });
- });
-
- }
-
- void dumpFrequencies() {
- printer.group('frequencies', () {
- frequencyMaps.forEach((key, Map<dynamic, List> map) {
- printer.child('frequency', {'title': '$key'}, () {
- dumpFrequency(map);
- });
- });
- });
- }
-
- void dumpFrequency(Map<dynamic, Iterable> map) {
- Map sortedMap = trySortMap(map);
- sortedMap.forEach((k, list) {
- dumpIterable('examples', '$k', list, limit: printer.examples);
- });
- }
-
- void dumpCounters() {
- printer.group('counters', () {
- countersMap.keys.forEach(dumpCounter);
- });
- }
-
- void dumpCounter(id) {
- Map<dynamic, List> map = countersMap[id];
- bool hasData(example) {
- if (map == null) return false;
- List list = map[example];
- if (list == null) return false;
- return list.any((data) => data != null);
- }
-
- int count = 0;
- Map<dynamic, int> frequencyMap = {};
- map.forEach((var category, List examples) {
- if (category != null) {
- frequencyMap.putIfAbsent(category, () => 0);
- frequencyMap[category] += examples.length;
- }
- count += examples.length;
- });
- Map<int, Set> result = sortMap(inverseMap(frequencyMap), (a, b) => b - a);
- int examplesLimit = null;
- if (printer.examples != null && result.length >= printer.examples) {
- examplesLimit = 0;
- }
- int counter = 0;
- bool hasMore = false;
- printer.open('counter', {'title': '$id', 'count': count});
- result.forEach((int count, Set examples) {
- if (counter == printer.examples) {
- printer.beginExtra();
- hasMore = true;
- }
- if (examples.length == 1 &&
- (examplesLimit == 0 || !hasData(examples.first))) {
- printer.child('examples', {'count': count, 'example': examples.first});
- } else {
- printer.child('examples',
- {'count': count, 'examples': examples.length},
- () {
- examples.forEach((example) {
- dumpIterable(
- 'examples', '$example', map[example],
- limit: examplesLimit,
- includeCount: false);
- });
- });
- }
- counter++;
- });
- if (hasMore) {
- printer.endExtra();
- }
- printer.close('counter');
- }
-
- void dumpTraces() {
- printer.group('traces', () {
- traceMap.keys.forEach(dumpTrace);
- });
- }
-
- void dumpTrace(key) {
- _StackTraceTree tree = traceMap[key];
- tree.dumpTraces(printer);
- }
-
- void dumpCorrelation(keyA, Iterable a, keyB, Iterable b,
- {Map dataA, Map dataB}) {
- printer.child('correlations', {'title': '$keyA vs $keyB'}, () {
- List aAndB = a.where((e) => e != null && b.contains(e)).toList();
- List aAndNotB = a.where((e) => e != null && !b.contains(e)).toList();
- List notAandB = b.where((e) => e != null && !a.contains(e)).toList();
- dumpIterable('correlation', '$keyA && $keyB', aAndB, dataMap: dataA,
- limit: printer.examples);
- dumpIterable('correlation', '$keyA && !$keyB', aAndNotB, dataMap: dataA,
- limit: printer.examples);
- dumpIterable('correlation', '!$keyA && $keyB', notAandB, dataMap: dataB,
- limit: printer.examples);
- });
- }
-
- void dumpIterable(String tag, String title, Iterable iterable,
- {int limit, Map dataMap, bool includeCount: true}) {
- if (limit == 0) return;
-
- Map childData = {};
- Iterable nonNullIterable = iterable.where((e) => e != null);
- if (nonNullIterable.isEmpty && !includeCount) {
- childData['name'] = title;
- } else {
- childData['title'] = title;
- }
- if (includeCount) {
- childData['count'] = iterable.length;
- }
- printer.child(tag, childData, () {
- bool hasMore = false;
- int counter = 0;
- nonNullIterable.forEach((element) {
- if (counter == limit) {
- printer.beginExtra();
- hasMore = true;
- }
- var data = dataMap != null ? dataMap[element] : null;
- if (data != null) {
- printer.child('example', {'value': element, 'data': data});
- } else {
- printer.child('example', {'value': element});
- }
- counter++;
- });
- if (hasMore) {
- printer.endExtra();
- }
- });
- }
-}
-
-/// Returns a map that is an inversion of [map], where the keys are the values
-/// of [map] and the values are the set of keys in [map] that share values.
-///
-/// If [equals] and [hashCode] are provided, these are used to determine
-/// equality among the values of [map].
-///
-/// If [isValidKey] is provided, this is used to determine with a value of [map]
-/// is a potential key of the inversion map.
-Map<dynamic, Set> inverseMap(Map map,
- {bool equals(key1, key2),
- int hashCode(key),
- bool isValidKey(potentialKey)}) {
- Map<dynamic, Set> result = new LinkedHashMap<dynamic, Set>(
- equals: equals, hashCode: hashCode, isValidKey: isValidKey);
- map.forEach((k, v) {
- if (isValidKey == null || isValidKey(v)) {
- result.putIfAbsent(v, () => new Set()).add(k);
- }
- });
- return result;
-}
-
-/// Return a new map heuristically sorted by the keys of [map]. If the first
-/// key of [map] is [Comparable], the keys are sorted using [sortMap] under
-/// the assumption that all keys are [Comparable].
-/// Otherwise, the keys are sorted as string using their `toString`
-/// representation.
-Map trySortMap(Map map) {
- Iterable iterable = map.keys.where((k) => k != null);
- if (iterable.isEmpty) return map;
- var key = iterable.first;
- if (key is Comparable) {
- return sortMap(map);
- }
- return sortMap(map, (a, b) => '$a'.compareTo('$b'));
-}
-
-/// Returns a new map in which the keys of [map] are sorted using [compare].
-/// If [compare] is null, the keys must be [Comparable].
-Map sortMap(Map map, [int compare(a,b)]) {
- List keys = map.keys.toList();
- keys.sort(compare);
- Map sortedMap = new Map();
- keys.forEach((k) => sortedMap[k] = map[k]);
- return sortedMap;
-}
-

Powered by Google App Engine
This is Rietveld 408576698