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

Side by Side Diff: runtime/bin/vmservice/client/lib/src/elements/isolate_profile.dart

Issue 237683004: Disable applyAuthorStyles (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 8 months 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library isolate_profile_element; 5 library isolate_profile_element;
6 6
7 import 'dart:html'; 7 import 'dart:html';
8 import 'observatory_element.dart'; 8 import 'observatory_element.dart';
9 import 'package:logging/logging.dart'; 9 import 'package:logging/logging.dart';
10 import 'package:observatory/service.dart'; 10 import 'package:observatory/service.dart';
11 import 'package:observatory/app.dart'; 11 import 'package:observatory/app.dart';
12 import 'package:polymer/polymer.dart'; 12 import 'package:polymer/polymer.dart';
13 13
14 class ProfileCodeTrieNodeTreeRow extends TableTreeRow { 14 class ProfileCodeTrieNodeTreeRow extends TableTreeRow {
15 final ServiceMap profile; 15 final ServiceMap profile;
16 @reflectable final CodeTrieNode root; 16 @reflectable final CodeTrieNode root;
17 @reflectable final CodeTrieNode node; 17 @reflectable final CodeTrieNode node;
18 @reflectable Code get code => node.code; 18 @reflectable Code get code => node.code;
19 19
20 static String formatPercent(num a, num total) { 20 @reflectable String tipKind = '';
21 var percent = 100.0 * (a / total); 21 @reflectable String tipParent = '';
22 return '${percent.toStringAsFixed(2)}%'; 22 @reflectable String tipExclusive = '';
23 } 23 @reflectable String tipTicks = '';
24 @reflectable String tipTime = '';
24 25
25 ProfileCodeTrieNodeTreeRow(this.profile, this.root, this.node, 26 ProfileCodeTrieNodeTreeRow(this.profile, this.root, this.node,
26 ProfileCodeTrieNodeTreeRow parent) 27 ProfileCodeTrieNodeTreeRow parent)
27 : super(parent) { 28 : super(parent) {
28 assert(root != null); 29 assert(root != null);
29 assert(node != null); 30 assert(node != null);
30 var totalSamples = root.count; 31 tipTicks = '${node.count}';
31 // When the row is created, fill out the columns. 32 var period = profile['period'];
32 if (parent == null) { 33 var MICROSECONDS_PER_SECOND = 1000000.0;
33 columns.add(formatPercent(node.count, root.count)); 34 var seconds = (period * node.count) / MICROSECONDS_PER_SECOND; // seconds
35 tipTime = Utils.formatTimePrecise(seconds);
36 if (code.kind == CodeKind.Tag) {
37 tipKind = 'Tag (category)';
38 if (parent == null) {
39 tipParent = Utils.formatPercent(node.count, root.count);
40 } else {
41 tipParent = Utils.formatPercent(node.count, parent.node.count);
42 }
43 tipExclusive = Utils.formatPercent(node.count, root.count);
34 } else { 44 } else {
35 columns.add(formatPercent(node.count, parent.node.count)); 45 if ((code.kind == CodeKind.Collected) ||
46 (code.kind == CodeKind.Reused)) {
47 tipKind = 'Garbage Collected Code';
48 } else {
49 tipKind = '${code.kind} (Function)';
50 }
51 if (parent == null) {
52 tipParent = Utils.formatPercent(node.count, root.count);
53 } else {
54 tipParent = Utils.formatPercent(node.count, parent.node.count);
55 }
56 tipExclusive = Utils.formatPercent(node.code.exclusiveTicks, root.count);
36 } 57 }
37 columns.add(formatPercent(node.code.exclusiveTicks, totalSamples)); 58 columns.add(tipParent);
59 columns.add(tipExclusive);
38 } 60 }
39 61
40 bool shouldDisplayChild(CodeTrieNode childNode, double threshold) { 62 bool shouldDisplayChild(CodeTrieNode childNode, double threshold) {
41 return ((childNode.count / node.count) > threshold) || 63 return ((childNode.count / node.count) > threshold) ||
42 ((childNode.code.exclusiveTicks / root.count) > threshold); 64 ((childNode.code.exclusiveTicks / root.count) > threshold);
43 } 65 }
44 66
45 void onShow() { 67 void onShow() {
46 var threshold = profile['threshold']; 68 var threshold = profile['threshold'];
47 if (children.length > 0) { 69 if (children.length > 0) {
48 // Child rows already created. 70 // Child rows already created.
49 return; 71 return;
50 } 72 }
51 for (var childNode in node.children) { 73 for (var childNode in node.children) {
52 if (!shouldDisplayChild(childNode, threshold)) { 74 if (!shouldDisplayChild(childNode, threshold)) {
53 continue; 75 continue;
54 } 76 }
55 var row = new ProfileCodeTrieNodeTreeRow(profile, root, childNode, this); 77 var row = new ProfileCodeTrieNodeTreeRow(profile, root, childNode, this);
56 children.add(row); 78 children.add(row);
57 } 79 }
58 } 80 }
59 81
60 void onHide() { 82 void onHide() {
61 } 83 }
62 } 84 }
63 85
64 class ProfileCallerTreeRow extends TableTreeRow {
65 final ServiceMap profile;
66 @reflectable final Code code;
67
68 static String formatPercent(num a, num total) {
69 var percent = 100.0 * (a / total);
70 return '${percent.toStringAsFixed(2)}%';
71 }
72
73 ProfileCallerTreeRow(this.profile, this.code, ProfileCallerTreeRow parent) :
74 super(parent) {
75 assert(profile != null);
76 assert(code != null);
77 var totalSamples = profile['samples'];
78 // When the row is created, fill out the columns.
79 if (parent == null) {
80 var root = profile.isolate.tagRoot();
81 var totalAttributedCalls = root.callersCount(code);
82 var totalParentCalls = root.sumCallersCount();
83 columns.add(formatPercent(totalAttributedCalls, totalParentCalls));
84 } else {
85 var totalAttributedCalls = parent.code.callersCount(code);
86 var totalParentCalls = parent.code.sumCallersCount();
87 columns.add(formatPercent(totalAttributedCalls, totalParentCalls));
88 }
89 columns.add(formatPercent(code.exclusiveTicks, totalSamples));
90 }
91
92 bool shouldDisplayChild(CodeCallCount childNode, totalSamples,
93 double threshold) {
94 var callerPercent = code.callersCount(childNode.code) /
95 code.sumCallersCount();
96 return (callerPercent > threshold) ||
97 ((childNode.code.exclusiveTicks / totalSamples) > threshold);
98 }
99
100 void onShow() {
101 var threshold = profile['threshold'];
102 var totalSamples = profile['samples'];
103 if (children.length > 0) {
104 // Child rows already created.
105 return;
106 }
107 for (var codeCaller in code.callers) {
108 if (!shouldDisplayChild(codeCaller, totalSamples, threshold)) {
109 continue;
110 }
111 var row = new ProfileCallerTreeRow(profile, codeCaller.code, this);
112 children.add(row);
113 }
114 }
115
116 void onHide() {
117 }
118 }
119
120 /// Displays an IsolateProfile 86 /// Displays an IsolateProfile
121 @CustomTag('isolate-profile') 87 @CustomTag('isolate-profile')
122 class IsolateProfileElement extends ObservatoryElement { 88 class IsolateProfileElement extends ObservatoryElement {
123 IsolateProfileElement.created() : super.created(); 89 IsolateProfileElement.created() : super.created();
124 @published ServiceMap profile; 90 @published ServiceMap profile;
125 @observable bool callGraphChecked;
126 @observable bool hideTagsChecked; 91 @observable bool hideTagsChecked;
127 @observable String sampleCount = ''; 92 @observable String sampleCount = '';
128 @observable String refreshTime = ''; 93 @observable String refreshTime = '';
129 @observable String sampleRate = ''; 94 @observable String sampleRate = '';
130 @observable String sampleDepth = ''; 95 @observable String sampleDepth = '';
131 @observable String displayCutoff = ''; 96 @observable String displayCutoff = '';
132 @reflectable double displayThreshold = 0.0001; // 0.5%. 97 @observable String timeSpan = '';
98 @reflectable double displayThreshold = 0.0002; // 0.02%.
99
100 @observable String tagSelector = 'uv';
133 101
134 final _id = '#tableTree'; 102 final _id = '#tableTree';
135 TableTree tree; 103 TableTree tree;
136 104
137 static const MICROSECONDS_PER_SECOND = 1000000.0; 105 static const MICROSECONDS_PER_SECOND = 1000000.0;
138 106
139 void profileChanged(oldValue) { 107 void profileChanged(oldValue) {
140 if (profile == null) { 108 if (profile == null) {
141 return; 109 return;
142 } 110 }
143 var totalSamples = profile['samples']; 111 var totalSamples = profile['samples'];
144 var now = new DateTime.now(); 112 var now = new DateTime.now();
145 sampleCount = totalSamples.toString(); 113 sampleCount = totalSamples.toString();
146 refreshTime = now.toString(); 114 refreshTime = now.toString();
147 sampleDepth = profile['depth'].toString(); 115 sampleDepth = profile['depth'].toString();
148 var period = profile['period']; 116 var period = profile['period'];
149 sampleRate = (MICROSECONDS_PER_SECOND / period).toStringAsFixed(0); 117 sampleRate = (MICROSECONDS_PER_SECOND / period).toStringAsFixed(0);
118 timeSpan = formatTime(profile['timeSpan']);
150 displayCutoff = '${(displayThreshold * 100.0).toString()}%'; 119 displayCutoff = '${(displayThreshold * 100.0).toString()}%';
151 profile.isolate.processProfile(profile); 120 profile.isolate.processProfile(profile);
152 profile['threshold'] = displayThreshold; 121 profile['threshold'] = displayThreshold;
153 _update(); 122 _update();
154 } 123 }
155 124
156 void callGraphCheckedChanged(oldValue) {
157 _update();
158 }
159
160 125
161 void enteredView() { 126 void enteredView() {
162 tree = new TableTree(); 127 tree = new TableTree();
163 _update(); 128 _update();
164 } 129 }
165 130
166 void hideTagsCheckedChanged(oldValue) { 131 void tagSelectorChanged(oldValue) {
167 refresh(null); 132 refresh(null);
168 } 133 }
169 134
170 void refresh(var done) { 135 void refresh(var done) {
171 var request = 'profile'; 136 var request = 'profile?tags=$tagSelector';
172 if ((hideTagsChecked != null) && hideTagsChecked) {
173 request += '?tags=hide';
174 }
175 profile.isolate.get(request).then((ServiceMap m) { 137 profile.isolate.get(request).then((ServiceMap m) {
176 // Assert we got back the a profile. 138 // Assert we got back the a profile.
177 assert(m.serviceType == 'Profile'); 139 assert(m.serviceType == 'Profile');
178 profile = m; 140 profile = m;
179 }).whenComplete(done); 141 }).whenComplete(done);
180 } 142 }
181 143
182 void _update() { 144 void _update() {
183 if (profile == null) { 145 if (profile == null) {
184 return; 146 return;
185 } 147 }
186 _buildTree(); 148 _buildTree();
187 } 149 }
188 150
189 void _buildCallersTree() {
190 assert(profile != null);
191 var root = profile.isolate.tagRoot();
192 if (root == null) {
193 Logger.root.warning('No profile root tag.');
194 }
195 try {
196 tree.initialize(new ProfileCallerTreeRow(profile, root, null));
197 } catch (e, stackTrace) {
198 Logger.root.warning('_buildCallersTree', e, stackTrace);
199 }
200
201 notifyPropertyChange(#tree, null, tree);
202 }
203
204 void _buildStackTree() { 151 void _buildStackTree() {
205 var root = profile.isolate.profileTrieRoot; 152 var root = profile.isolate.profileTrieRoot;
206 if (root == null) { 153 if (root == null) {
207 Logger.root.warning('No profile trie root.'); 154 return;
208 } 155 }
209 try { 156 try {
210 tree.initialize( 157 tree.initialize(
211 new ProfileCodeTrieNodeTreeRow(profile, root, root, null)); 158 new ProfileCodeTrieNodeTreeRow(profile, root, root, null));
212 } catch (e, stackTrace) { 159 } catch (e, stackTrace) {
213 Logger.root.warning('_buildStackTree', e, stackTrace); 160 Logger.root.warning('_buildStackTree', e, stackTrace);
214 } 161 }
215 notifyPropertyChange(#tree, null, tree); 162 notifyPropertyChange(#tree, null, tree);
216 } 163 }
217 164
218 void _buildTree() { 165 void _buildTree() {
219 if ((callGraphChecked) != null && callGraphChecked) { 166 _buildStackTree();
220 _buildCallersTree();
221 } else {
222 _buildStackTree();
223 }
224 } 167 }
225 168
226 @observable String padding(TableTreeRow row) { 169 @observable String padding(TableTreeRow row) {
227 return 'padding-left: ${row.depth * 16}px;'; 170 return 'padding-left: ${row.depth * 16}px;';
228 } 171 }
229 172
230 @observable String coloring(TableTreeRow row) { 173 @observable String coloring(TableTreeRow row) {
231 const colors = const ['active', 'success', 'warning', 'danger', 'info']; 174 const colors = const ['rowColor0', 'rowColor1', 'rowColor2', 'rowColor3',
232 var index = row.depth % colors.length; 175 'rowColor4', 'rowColor5', 'rowColor6', 'rowColor7',
176 'rowColor8'];
177 var index = (row.depth - 1) % colors.length;
233 return colors[index]; 178 return colors[index];
234 } 179 }
235 180
236 @observable void toggleExpanded(Event e, var detail, Element target) { 181 @observable void toggleExpanded(Event e, var detail, Element target) {
237 // We only want to expand a tree row if the target of the click is 182 // We only want to expand a tree row if the target of the click is
238 // the table cell (passed in as target) or the span containing the 183 // the table cell (passed in as target) or the span containing the
239 // expander symbol (#expand). 184 // expander symbol (#expand).
240 if ((e.target.id != 'expand') && (e.target != target)) { 185 if ((e.target.id != 'expand') && (e.target != target)) {
241 // Target of click was not the expander span or the table cell. 186 // Target of click was not the expander span or the table cell.
242 return; 187 return;
243 } 188 }
244 var row = target.parent; 189 var row = target.parent;
245 if (row is TableRowElement) { 190 if (row is TableRowElement) {
246 // Subtract 1 to get 0 based indexing. 191 // Subtract 1 to get 0 based indexing.
247 tree.toggle(row.rowIndex - 1); 192 try {
193 tree.toggle(row.rowIndex - 1);
194 } catch (e, stackTrace) {
195 Logger.root.warning('toggleExpanded', e, stackTrace);
196 }
248 } 197 }
249 } 198 }
250 } 199 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698