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

Side by Side Diff: chrome/browser/resources/tracing/timeline_track.js

Issue 9706010: about:tracing support for TRACE_ASYNC_START/FINISH events. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: try again Created 8 years, 9 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 5
6 /** 6 /**
7 * @fileoverview Renders an array of slices into the provided div, 7 * @fileoverview Renders an array of slices into the provided div,
8 * using a child canvas element. Uses a FastRectRenderer to draw only 8 * using a child canvas element. Uses a FastRectRenderer to draw only
9 * the visible slices. 9 * the visible slices.
10 */ 10 */
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 for (var i = 0; i < this.tracks_.length; i++) { 104 for (var i = 0; i < this.tracks_.length; i++) {
105 var trackClientRect = this.tracks_[i].getBoundingClientRect(); 105 var trackClientRect = this.tracks_[i].getBoundingClientRect();
106 var a = Math.max(loY, trackClientRect.top); 106 var a = Math.max(loY, trackClientRect.top);
107 var b = Math.min(hiY, trackClientRect.bottom); 107 var b = Math.min(hiY, trackClientRect.bottom);
108 if (a <= b) 108 if (a <= b)
109 this.tracks_[i].pickRange(loWX, hiWX, loY, hiY, onHitCallback); 109 this.tracks_[i].pickRange(loWX, hiWX, loY, hiY, onHitCallback);
110 } 110 }
111 } 111 }
112 }; 112 };
113 113
114 function addCloseButtonElement(el) {
115 var closeEl = document.createElement('div');
116 closeEl.classList.add('timeline-track-button');
117 closeEl.classList.add('timeline-track-close-button');
118 closeEl.textContent = String.fromCharCode(215); // &times;
119 closeEl.addEventListener('click', function() {
120 el.style.display = 'None';
121 });
122 el.appendChild(closeEl);
123 }
124
114 /** 125 /**
115 * Visualizes a TimelineThread using a series of of TimelineSliceTracks. 126 * Visualizes a TimelineThread using a series of of TimelineSliceTracks.
116 * @constructor 127 * @constructor
117 */ 128 */
118 var TimelineThreadTrack = cr.ui.define(TimelineContainerTrack); 129 var TimelineThreadTrack = cr.ui.define(TimelineContainerTrack);
119 TimelineThreadTrack.prototype = { 130 TimelineThreadTrack.prototype = {
120 __proto__: TimelineContainerTrack.prototype, 131 __proto__: TimelineContainerTrack.prototype,
121 132
122 decorate: function() { 133 decorate: function() {
123 this.classList.add('timeline-thread-track'); 134 this.classList.add('timeline-thread-track');
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 updateChildTracks_: function() { 185 updateChildTracks_: function() {
175 this.detach(); 186 this.detach();
176 this.textContent = ''; 187 this.textContent = '';
177 this.tracks_ = []; 188 this.tracks_ = [];
178 if (this.thread_) { 189 if (this.thread_) {
179 if (this.thread_.cpuSlices) { 190 if (this.thread_.cpuSlices) {
180 var track = this.addTrack_(this.thread_.cpuSlices); 191 var track = this.addTrack_(this.thread_.cpuSlices);
181 track.height = '4px'; 192 track.height = '4px';
182 } 193 }
183 194
184 for (var srI = 0; srI < this.thread_.nonNestedSubRows.length; ++srI) { 195 if (this.thread_.asyncSlices.length) {
185 this.addTrack_(this.thread_.nonNestedSubRows[srI]); 196 var subRows = this.thread_.asyncSlices.subRows;
197 for (var srI = 0; srI < subRows.length; srI++) {
198 var track = this.addTrack_(subRows[srI]);
199 track.asyncStyle = true;
200 }
186 } 201 }
187 for (var srI = 0; srI < this.thread_.subRows.length; ++srI) { 202
203 for (var srI = 0; srI < this.thread_.subRows.length; srI++) {
188 this.addTrack_(this.thread_.subRows[srI]); 204 this.addTrack_(this.thread_.subRows[srI]);
189 } 205 }
206
190 if (this.tracks_.length > 0) { 207 if (this.tracks_.length > 0) {
191 if (this.thread_.cpuSlices) { 208 if (this.thread_.cpuSlices) {
192 this.tracks_[1].heading = this.heading_; 209 this.tracks_[1].heading = this.heading_;
193 this.tracks_[1].tooltip = this.tooltip_; 210 this.tracks_[1].tooltip = this.tooltip_;
194 } else { 211 } else {
195 this.tracks_[0].heading = this.heading_; 212 this.tracks_[0].heading = this.heading_;
196 this.tracks_[0].tooltip = this.tooltip_; 213 this.tracks_[0].tooltip = this.tooltip_;
197 } 214 }
198 } 215 }
199 } 216 }
217 addCloseButtonElement(this);
200 } 218 }
201 }; 219 };
202 220
203 /** 221 /**
204 * Visualizes a TimelineCpu using a series of of TimelineSliceTracks. 222 * Visualizes a TimelineCpu using a series of of TimelineSliceTracks.
205 * @constructor 223 * @constructor
206 */ 224 */
207 var TimelineCpuTrack = cr.ui.define(TimelineContainerTrack); 225 var TimelineCpuTrack = cr.ui.define(TimelineContainerTrack);
208 TimelineCpuTrack.prototype = { 226 TimelineCpuTrack.prototype = {
209 __proto__: TimelineContainerTrack.prototype, 227 __proto__: TimelineContainerTrack.prototype,
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 track.slices = this.cpu_.slices; 275 track.slices = this.cpu_.slices;
258 track.headingWidth = this.headingWidth_; 276 track.headingWidth = this.headingWidth_;
259 track.viewport = this.viewport_; 277 track.viewport = this.viewport_;
260 278
261 this.tracks_.push(track); 279 this.tracks_.push(track);
262 this.appendChild(track); 280 this.appendChild(track);
263 281
264 this.tracks_[0].heading = this.heading_; 282 this.tracks_[0].heading = this.heading_;
265 this.tracks_[0].tooltip = this.tooltip_; 283 this.tracks_[0].tooltip = this.tooltip_;
266 } 284 }
285 addCloseButtonElement(this);
267 } 286 }
268 }; 287 };
269 288
270 /** 289 /**
271 * A canvas-based track constructed. Provides the basic heading and 290 * A canvas-based track constructed. Provides the basic heading and
272 * invalidation-managment infrastructure. Subclasses must implement drawing 291 * invalidation-managment infrastructure. Subclasses must implement drawing
273 * and picking code. 292 * and picking code.
274 * @constructor 293 * @constructor
275 * @extends {HTMLDivElement} 294 * @extends {HTMLDivElement}
276 */ 295 */
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
359 }.bind(this), this); 378 }.bind(this), this);
360 this.rafPending_ = true; 379 this.rafPending_ = true;
361 }, 380 },
362 381
363 get firstCanvas() { 382 get firstCanvas() {
364 return this.canvas_; 383 return this.canvas_;
365 } 384 }
366 385
367 }; 386 };
368 387
369 /** 388 /**
370 * A pair representing an elided string and world-coordinate width 389 * A pair representing an elided string and world-coordinate width
371 * to draw it. 390 * to draw it.
372 * @constructor 391 * @constructor
373 */ 392 */
374 function ElidedStringWidthPair(string, width) { 393 function ElidedStringWidthPair(string, width) {
375 this.string = string; 394 this.string = string;
376 this.width = width; 395 this.width = width;
377 } 396 }
378 397
398 /**
399 * A cache for elided strings.
400 * @constructor
401 */
402 function ElidedTitleCache() {
403 }
404
405 ElidedTitleCache.prototype = {
379 /** 406 /**
380 * A cache for elided strings. 407 * Return elided text.
381 * @constructor 408 * @param {track} A timeline slice track or other object that defines
382 */ 409 * functions labelWidth() and labelWidthWorld().
383 function ElidedTitleCache() { 410 * @param {pixWidth} Pixel width.
384 } 411 * @param {title} Original title text.
385 412 * @param {width} Drawn width in world coords.
386 ElidedTitleCache.prototype = { 413 * @param {sliceDuration} Where the title must fit (in world coords).
387 /** 414 * @return {ElidedStringWidthPair} Elided string and width.
388 * Return elided text. 415 */
389 * @param {track} A timeline slice track or other object that defines 416 get: function(track, pixWidth, title, width, sliceDuration) {
390 * functions labelWidth() and labelWidthWorld(). 417 var elidedDict = elidedTitleCacheDict[title];
391 * @param {pixWidth} Pixel width. 418 if (!elidedDict) {
392 * @param {title} Original title text. 419 elidedDict = {};
393 * @param {width} Drawn width in world coords. 420 elidedTitleCacheDict[title] = elidedDict;
394 * @param {sliceDuration} Where the title must fit (in world coords). 421 }
395 * @return {ElidedStringWidthPair} Elided string and width. 422 var elidedDictForPixWidth = elidedDict[pixWidth];
396 */ 423 if (!elidedDictForPixWidth) {
397 get: function(track, pixWidth, title, width, sliceDuration) { 424 elidedDict[pixWidth] = {};
398 var elidedDict = elidedTitleCacheDict[title]; 425 elidedDictForPixWidth = elidedDict[pixWidth];
399 if (!elidedDict) { 426 }
400 elidedDict = {}; 427 var stringWidthPair = elidedDictForPixWidth[sliceDuration];
401 elidedTitleCacheDict[title] = elidedDict; 428 if (stringWidthPair === undefined) {
402 } 429 var newtitle = title;
403 var stringWidthPair = elidedDict[sliceDuration]; 430 var elided = false;
404 if (stringWidthPair === undefined) { 431 while (track.labelWidthWorld(newtitle, pixWidth) > sliceDuration) {
405 var newtitle = title; 432 newtitle = newtitle.substring(0, newtitle.length * 0.75);
406 var elided = false; 433 elided = true;
407 while (track.labelWidthWorld(newtitle, pixWidth) > sliceDuration) { 434 }
408 newtitle = newtitle.substring(0, newtitle.length * 0.75); 435 if (elided && newtitle.length > 3)
409 elided = true; 436 newtitle = newtitle.substring(0, newtitle.length - 3) + '...';
410 } 437 stringWidthPair = new ElidedStringWidthPair(
411 if (elided && newtitle.length > 3) 438 newtitle,
412 newtitle = newtitle.substring(0, newtitle.length - 3) + '...'; 439 track.labelWidth(newtitle));
413 stringWidthPair = new ElidedStringWidthPair( 440 elidedDictForPixWidth[sliceDuration] = stringWidthPair;
414 newtitle, 441 }
415 track.labelWidth(newtitle)); 442 return stringWidthPair;
416 elidedDict[sliceDuration] = stringWidthPair; 443 }
417 } 444 };
418 return stringWidthPair;
419 },
420 };
421 445
422 /** 446 /**
423 * A track that displays an array of TimelineSlice objects. 447 * A track that displays an array of TimelineSlice objects.
424 * @constructor 448 * @constructor
425 * @extends {CanvasBasedTrack} 449 * @extends {CanvasBasedTrack}
426 */ 450 */
427 451
428 var TimelineSliceTrack = cr.ui.define(CanvasBasedTrack); 452 var TimelineSliceTrack = cr.ui.define(CanvasBasedTrack);
429 453
430 TimelineSliceTrack.prototype = { 454 TimelineSliceTrack.prototype = {
431 455
432 __proto__: CanvasBasedTrack.prototype, 456 __proto__: CanvasBasedTrack.prototype,
433 457
434 /** 458 /**
435 * Should we elide text on trace labels? 459 * Should we elide text on trace labels?
436 * Without eliding, text that is too wide isn't drawn at all. 460 * Without eliding, text that is too wide isn't drawn at all.
437 * Disable if you feel this causes a performance problem. 461 * Disable if you feel this causes a performance problem.
438 * This is a default value that can be overridden in tracks for testing. 462 * This is a default value that can be overridden in tracks for testing.
439 * @const 463 * @const
440 */ 464 */
441 SHOULD_ELIDE_TEXT: true, 465 SHOULD_ELIDE_TEXT: true,
442 466
443 decorate: function() { 467 decorate: function() {
444 this.classList.add('timeline-slice-track'); 468 this.classList.add('timeline-slice-track');
445 this.elidedTitleCache = new ElidedTitleCache(); 469 this.elidedTitleCache = new ElidedTitleCache();
470 this.asyncStyle_ = false;
471 },
472
473 get asyncStyle() {
474 return this.asyncStyle_;
475 },
476
477 set asyncStyle(v) {
478 this.asyncStyle_ = !!v;
479 this.invalidate();
446 }, 480 },
447 481
448 get slices() { 482 get slices() {
449 return this.slices_; 483 return this.slices_;
450 }, 484 },
451 485
452 set slices(slices) { 486 set slices(slices) {
453 this.slices_ = slices; 487 this.slices_ = slices;
454 this.invalidate(); 488 this.invalidate();
455 }, 489 },
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
496 } 530 }
497 ctx.strokeStyle = 'rgba(255,0,0,0.25)'; 531 ctx.strokeStyle = 'rgba(255,0,0,0.25)';
498 ctx.stroke(); 532 ctx.stroke();
499 } 533 }
500 534
501 // Begin rendering in world space. 535 // Begin rendering in world space.
502 ctx.save(); 536 ctx.save();
503 vp.applyTransformToCanavs(ctx); 537 vp.applyTransformToCanavs(ctx);
504 538
505 // Slices. 539 // Slices.
540 if (this.asyncStyle_)
541 ctx.globalAlpha = 0.25;
506 var tr = new tracing.FastRectRenderer(ctx, viewLWorld, 2 * pixWidth, 542 var tr = new tracing.FastRectRenderer(ctx, viewLWorld, 2 * pixWidth,
507 2 * pixWidth, viewRWorld, pallette); 543 2 * pixWidth, viewRWorld, pallette);
508 tr.setYandH(0, canvasH); 544 tr.setYandH(0, canvasH);
509 var slices = this.slices_; 545 var slices = this.slices_;
510 for (var i = 0; i < slices.length; ++i) { 546 for (var i = 0; i < slices.length; ++i) {
511 var slice = slices[i]; 547 var slice = slices[i];
512 var x = slice.start; 548 var x = slice.start;
513 // Less than 0.001 causes short events to disappear when zoomed in. 549 // Less than 0.001 causes short events to disappear when zoomed in.
514 var w = Math.max(slice.duration, 0.001); 550 var w = Math.max(slice.duration, 0.001);
515 var colorId = slice.selected ? 551 var colorId = slice.selected ?
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
553 var slice = slices[i]; 589 var slice = slices[i];
554 if (slice.duration > quickDiscardThresshold) { 590 if (slice.duration > quickDiscardThresshold) {
555 var title = slice.title; 591 var title = slice.title;
556 if (slice.didNotFinish) { 592 if (slice.didNotFinish) {
557 title += ' (Did Not Finish)'; 593 title += ' (Did Not Finish)';
558 } 594 }
559 var drawnTitle = title; 595 var drawnTitle = title;
560 var drawnWidth = this.labelWidth(drawnTitle); 596 var drawnWidth = this.labelWidth(drawnTitle);
561 if (shouldElide && 597 if (shouldElide &&
562 this.labelWidthWorld(drawnTitle, pixWidth) > slice.duration) { 598 this.labelWidthWorld(drawnTitle, pixWidth) > slice.duration) {
563 var elidedValues = this.elidedTitleCache.get( 599 var elidedValues = this.elidedTitleCache.get(
564 this, pixWidth, 600 this, pixWidth,
565 drawnTitle, drawnWidth, 601 drawnTitle, drawnWidth,
566 slice.duration); 602 slice.duration);
567 drawnTitle = elidedValues.string; 603 drawnTitle = elidedValues.string;
568 drawnWidth = elidedValues.width; 604 drawnWidth = elidedValues.width;
569 } 605 }
570 if (drawnWidth * pixWidth < slice.duration) { 606 if (drawnWidth * pixWidth < slice.duration) {
571 var cX = vp.xWorldToView(slice.start + 0.5 * slice.duration); 607 var cX = vp.xWorldToView(slice.start + 0.5 * slice.duration);
572 ctx.fillText(drawnTitle, cX, 2.5, drawnWidth); 608 ctx.fillText(drawnTitle, cX, 2.5, drawnWidth);
573 } 609 }
574 } 610 }
575 } 611 }
576 } 612 }
577 }, 613 },
578 614
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
684 /** 720 /**
685 * A track that displays the viewport size and scale. 721 * A track that displays the viewport size and scale.
686 * @constructor 722 * @constructor
687 * @extends {CanvasBasedTrack} 723 * @extends {CanvasBasedTrack}
688 */ 724 */
689 725
690 var TimelineViewportTrack = cr.ui.define(CanvasBasedTrack); 726 var TimelineViewportTrack = cr.ui.define(CanvasBasedTrack);
691 727
692 const logOf10 = Math.log(10); 728 const logOf10 = Math.log(10);
693 function log10(x) { 729 function log10(x) {
694 return Math.log(x) / logOf10;; 730 return Math.log(x) / logOf10;
695 } 731 }
696 732
697 TimelineViewportTrack.prototype = { 733 TimelineViewportTrack.prototype = {
698 734
699 __proto__: CanvasBasedTrack.prototype, 735 __proto__: CanvasBasedTrack.prototype,
700 736
701 decorate: function() { 737 decorate: function() {
702 this.classList.add('timeline-viewport-track'); 738 this.classList.add('timeline-viewport-track');
703 this.strings_ = {}; 739 this.strings_ = {};
704 }, 740 },
(...skipping 17 matching lines...) Expand all
722 758
723 // The conservative guess is the nearest enclosing 0.1, 1, 10, 100, etc 759 // The conservative guess is the nearest enclosing 0.1, 1, 10, 100, etc
724 var conservativeGuess = 760 var conservativeGuess =
725 Math.pow(10, Math.ceil(log10(idealMajorMarkDistanceWorld))); 761 Math.pow(10, Math.ceil(log10(idealMajorMarkDistanceWorld)));
726 762
727 // Once we have a conservative guess, consider things that evenly add up 763 // Once we have a conservative guess, consider things that evenly add up
728 // to the conservative guess, e.g. 0.5, 0.2, 0.1 Pick the one that still 764 // to the conservative guess, e.g. 0.5, 0.2, 0.1 Pick the one that still
729 // exceeds the ideal mark distance. 765 // exceeds the ideal mark distance.
730 var divisors = [10, 5, 2, 1]; 766 var divisors = [10, 5, 2, 1];
731 for (var i = 0; i < divisors.length; ++i) { 767 for (var i = 0; i < divisors.length; ++i) {
732 var tightenedGuess = conservativeGuess / divisors[i] 768 var tightenedGuess = conservativeGuess / divisors[i];
733 if (vp.xWorldVectorToView(tightenedGuess) < idealMajorMarkDistancePix) 769 if (vp.xWorldVectorToView(tightenedGuess) < idealMajorMarkDistancePix)
734 continue; 770 continue;
735 majorMarkDistanceWorld = conservativeGuess / divisors[i-1]; 771 majorMarkDistanceWorld = conservativeGuess / divisors[i - 1];
736 break; 772 break;
737 } 773 }
738 if (majorMarkDistanceWorld < 100) { 774 if (majorMarkDistanceWorld < 100) {
739 unit = 'ms'; 775 unit = 'ms';
740 unitDivisor = 1; 776 unitDivisor = 1;
741 } else { 777 } else {
742 unit = 's'; 778 unit = 's';
743 unitDivisor = 1000; 779 unitDivisor = 1000;
744 } 780 }
745 781
746 var numTicksPerMajor = 5; 782 var numTicksPerMajor = 5;
747 var minorMarkDistanceWorld = majorMarkDistanceWorld / numTicksPerMajor; 783 var minorMarkDistanceWorld = majorMarkDistanceWorld / numTicksPerMajor;
748 var minorMarkDistancePx = vp.xWorldVectorToView(minorMarkDistanceWorld); 784 var minorMarkDistancePx = vp.xWorldVectorToView(minorMarkDistanceWorld);
749 785
750 var firstMajorMark = 786 var firstMajorMark =
751 Math.floor(viewLWorld / majorMarkDistanceWorld) * 787 Math.floor(viewLWorld / majorMarkDistanceWorld) *
752 majorMarkDistanceWorld; 788 majorMarkDistanceWorld;
753 789
754 var minorTickH = Math.floor(canvasH * 0.25); 790 var minorTickH = Math.floor(canvasH * 0.25);
755 791
756 ctx.fillStyle = 'rgb(0, 0, 0)'; 792 ctx.fillStyle = 'rgb(0, 0, 0)';
757 ctx.strokeStyle = 'rgb(0, 0, 0)'; 793 ctx.strokeStyle = 'rgb(0, 0, 0)';
758 ctx.textAlign = 'left'; 794 ctx.textAlign = 'left';
759 ctx.textBaseline = 'top'; 795 ctx.textBaseline = 'top';
760 ctx.font = '9px sans-serif'; 796 ctx.font = '9px sans-serif';
761 797
762 // Each iteration of this loop draws one major mark 798 // Each iteration of this loop draws one major mark
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
834 */ 870 */
835 871
836 var TimelineCounterTrack = cr.ui.define(CanvasBasedTrack); 872 var TimelineCounterTrack = cr.ui.define(CanvasBasedTrack);
837 873
838 TimelineCounterTrack.prototype = { 874 TimelineCounterTrack.prototype = {
839 875
840 __proto__: CanvasBasedTrack.prototype, 876 __proto__: CanvasBasedTrack.prototype,
841 877
842 decorate: function() { 878 decorate: function() {
843 this.classList.add('timeline-counter-track'); 879 this.classList.add('timeline-counter-track');
880 addCloseButtonElement(this);
844 }, 881 },
845 882
846 get counter() { 883 get counter() {
847 return this.counter_; 884 return this.counter_;
848 }, 885 },
849 886
850 set counter(counter) { 887 set counter(counter) {
851 this.counter_ = counter; 888 this.counter_ = counter;
852 this.invalidate(); 889 this.invalidate();
853 }, 890 },
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
973 }; 1010 };
974 1011
975 return { 1012 return {
976 TimelineCounterTrack: TimelineCounterTrack, 1013 TimelineCounterTrack: TimelineCounterTrack,
977 TimelineSliceTrack: TimelineSliceTrack, 1014 TimelineSliceTrack: TimelineSliceTrack,
978 TimelineThreadTrack: TimelineThreadTrack, 1015 TimelineThreadTrack: TimelineThreadTrack,
979 TimelineViewportTrack: TimelineViewportTrack, 1016 TimelineViewportTrack: TimelineViewportTrack,
980 TimelineCpuTrack: TimelineCpuTrack 1017 TimelineCpuTrack: TimelineCpuTrack
981 }; 1018 };
982 }); 1019 });
OLDNEW
« no previous file with comments | « chrome/browser/resources/tracing/timeline_test.html ('k') | chrome/browser/resources/tracing/timeline_track_test.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698