OLD | NEW |
| (Empty) |
1 // Copyright (c) 2014, 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 part of dart2js.helpers; | |
6 | |
7 /** | |
8 * The track map is a simple wrapper around a map that keeps track | |
9 * of the 'final' size of maps grouped by description. It allows | |
10 * determining the distribution of sizes for a specific allocation | |
11 * site and it can be used like this: | |
12 * | |
13 * Map<String, int> map = new TrackMap<String, int>("my-map"); | |
14 * | |
15 * After finishing the compilaton, the histogram of track map sizes | |
16 * is printed but only when running in verbose mode. | |
17 */ | |
18 class TrackMap<K, V> implements Map<K, V> { | |
19 final Map _map; | |
20 final List _counts; | |
21 static final Map<String, List<int>> _countsMap = {}; | |
22 | |
23 TrackMap._internal(this._counts) : _map = new Map<K, V>(); | |
24 | |
25 factory TrackMap(String description) { | |
26 List counts = _countsMap.putIfAbsent(description, () => [ 0 ]); | |
27 Map result = new TrackMap<K, V>._internal(counts); | |
28 counts[0]++; | |
29 return result; | |
30 } | |
31 | |
32 static void printHistogram() { | |
33 _countsMap.forEach((description, counts) { | |
34 print('$description -- ${counts.length} maps'); | |
35 | |
36 // Count the total number of maps. | |
37 int sum = 0; | |
38 for (int i = 0; i < counts.length; i++) { | |
39 sum += counts[i]; | |
40 } | |
41 int increment = sum ~/ 10; | |
42 int target = increment; | |
43 int accumulated = 0; | |
44 for (int i = 0; i < counts.length; i++) { | |
45 accumulated += counts[i]; | |
46 if (accumulated >= target) { | |
47 String percent = (accumulated / sum * 100).toStringAsFixed(1); | |
48 print(' -- $percent%: length <= $i'); | |
49 target += increment; | |
50 } | |
51 } | |
52 }); | |
53 } | |
54 | |
55 int get length => _map.length; | |
56 bool get isEmpty => _map.isEmpty; | |
57 bool get isNotEmpty => _map.isNotEmpty; | |
58 | |
59 Iterable<K> get keys => _map.keys; | |
60 Iterable<V> get values => _map.values; | |
61 | |
62 bool containsKey(K key) => _map.containsKey(key); | |
63 bool containsValue(V value) => _map.containsValue(value); | |
64 | |
65 V operator[](K key) => _map[key]; | |
66 String toString() => _map.toString(); | |
67 | |
68 void forEach(void action(K key, V value)) { | |
69 _map.forEach(action); | |
70 } | |
71 | |
72 void operator[]=(K key, V value) { | |
73 if (!_map.containsKey(key)) { | |
74 _notifyLengthChanged(1); | |
75 _map[key] = value; | |
76 } | |
77 } | |
78 | |
79 V putIfAbsent(K key, V ifAbsent()) { | |
80 if (containsKey(key)) return this[key]; | |
81 V value = ifAbsent(); | |
82 this[key] = value; | |
83 return value; | |
84 } | |
85 | |
86 V remove(Object key) { | |
87 if (_map.containsKey(key)) { | |
88 _notifyLengthChanged(-1); | |
89 } | |
90 return _map.remove(key); | |
91 } | |
92 | |
93 void addAll(Map<K, V> other) { | |
94 other.forEach((key, value) => this[key] = value); | |
95 } | |
96 | |
97 void clear() { | |
98 _notifyLengthChanged(-_map.length); | |
99 _map.clear(); | |
100 } | |
101 | |
102 void _notifyLengthChanged(int delta) { | |
103 int oldLength = _map.length; | |
104 int newLength = oldLength + delta; | |
105 _counts[oldLength]--; | |
106 if (newLength < _counts.length) { | |
107 _counts[newLength]++; | |
108 } else { | |
109 _counts.add(1); | |
110 assert(newLength == _counts.length - 1); | |
111 } | |
112 } | |
113 } | |
OLD | NEW |