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

Side by Side Diff: Source/devtools/front_end/TimelineOverviewPane.js

Issue 61923003: Timeline: show impl-side frames on the Timeline overview (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: rebased, addressed review comments, added a test Created 7 years 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 /* 1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved. 2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 630 matching lines...) Expand 10 before | Expand all | Expand 10 after
641 * @param {WebInspector.TimelineModel} model 641 * @param {WebInspector.TimelineModel} model
642 */ 642 */
643 WebInspector.TimelineFrameOverview = function(model) 643 WebInspector.TimelineFrameOverview = function(model)
644 { 644 {
645 WebInspector.TimelineOverviewBase.call(this, model); 645 WebInspector.TimelineOverviewBase.call(this, model);
646 this.element.id = "timeline-overview-frames"; 646 this.element.id = "timeline-overview-frames";
647 this.reset(); 647 this.reset();
648 648
649 this._outerPadding = 4 * window.devicePixelRatio; 649 this._outerPadding = 4 * window.devicePixelRatio;
650 this._maxInnerBarWidth = 10 * window.devicePixelRatio; 650 this._maxInnerBarWidth = 10 * window.devicePixelRatio;
651 this._topPadding = 6 * window.devicePixelRatio;
651 652
652 // The below two are really computed by update() -- but let's have something so that windowTimes() is happy. 653 // The below two are really computed by update() -- but let's have something so that windowTimes() is happy.
653 this._actualPadding = 5 * window.devicePixelRatio; 654 this._actualPadding = 5 * window.devicePixelRatio;
654 this._actualOuterBarWidth = this._maxInnerBarWidth + this._actualPadding; 655 this._actualOuterBarWidth = this._maxInnerBarWidth + this._actualPadding;
655 656
656 this._fillStyles = {}; 657 this._fillStyles = {};
657 var categories = WebInspector.TimelinePresentationModel.categories(); 658 var categories = WebInspector.TimelinePresentationModel.categories();
658 for (var category in categories) 659 for (var category in categories)
659 this._fillStyles[category] = WebInspector.TimelinePresentationModel.crea teFillStyleForCategory(this._context, this._maxInnerBarWidth, 0, categories[cate gory]); 660 this._fillStyles[category] = WebInspector.TimelinePresentationModel.crea teFillStyleForCategory(this._context, this._maxInnerBarWidth, 0, categories[cate gory]);
661 this._frameTopShadeGradient = this._context.createLinearGradient(0, 0, 0, th is._topPadding);
662 this._frameTopShadeGradient.addColorStop(0, "rgba(255, 255, 255, 0.9)");
663 this._frameTopShadeGradient.addColorStop(1, "rgba(255, 255, 255, 0.2)");
660 } 664 }
661 665
662 WebInspector.TimelineFrameOverview.prototype = { 666 WebInspector.TimelineFrameOverview.prototype = {
663 reset: function() 667 reset: function()
664 { 668 {
665 this._recordsPerBar = 1; 669 this._recordsPerBar = 1;
666 /** @type {!Array.<{startTime:number, endTime:number}>} */ 670 /** @type {!Array.<{startTime:number, endTime:number}>} */
667 this._barTimes = []; 671 this._barTimes = [];
668 this._frames = []; 672 this._mainThreadFrames = [];
673 this._backgroundFrames = [];
674 this._framesById = {};
669 }, 675 },
670 676
671 update: function() 677 update: function()
672 { 678 {
673 this._resetCanvas(); 679 this._resetCanvas();
674 this._barTimes = []; 680 this._barTimes = [];
675 681
682 var backgroundFramesHeight = 15;
683 var mainThreadFramesHeight = this._canvas.height - backgroundFramesHeigh t;
676 const minBarWidth = 4 * window.devicePixelRatio; 684 const minBarWidth = 4 * window.devicePixelRatio;
677 var frameCount = this._frames.length; 685 var frameCount = this._backgroundFrames.length || this._mainThreadFrames .length;
678 var framesPerBar = Math.max(1, frameCount * minBarWidth / this._canvas.w idth); 686 var framesPerBar = Math.max(1, frameCount * minBarWidth / this._canvas.w idth);
679 var visibleFrames = this._aggregateFrames(this._frames, framesPerBar); 687
680 var windowHeight = this._canvas.height; 688 var mainThreadVisibleFrames;
681 const paddingTop = 4 * window.devicePixelRatio; 689 var backgroundVisibleFrames;
682 var scale = (windowHeight - paddingTop) / this._computeTargetFrameLength (visibleFrames); 690 if (this._backgroundFrames.length) {
683 this._renderBars(visibleFrames, scale, windowHeight); 691 backgroundVisibleFrames = this._aggregateFrames(this._backgroundFram es, framesPerBar);
684 this._drawFPSMarks(scale, windowHeight); 692 mainThreadVisibleFrames = new Array(backgroundVisibleFrames.length);
693 for (var i = 0; i < backgroundVisibleFrames.length; ++i) {
694 var frameId = backgroundVisibleFrames[i].mainThreadFrameId;
695 mainThreadVisibleFrames[i] = frameId && this._framesById[frameId ];
696 }
697 } else {
698 mainThreadVisibleFrames = this._aggregateFrames(this._mainThreadFram es, framesPerBar);
699 }
700
701 this._context.save();
702 this._setCanvasWindow(0, backgroundFramesHeight, this._canvas.width, mai nThreadFramesHeight);
703 var scale = (mainThreadFramesHeight - this._topPadding) / this._computeT argetFrameLength(mainThreadVisibleFrames);
704 this._renderBars(mainThreadVisibleFrames, scale, mainThreadFramesHeight) ;
705 this._context.fillStyle = this._frameTopShadeGradient;
706 this._context.fillRect(0, 0, this._canvas.width, this._topPadding);
707 this._drawFPSMarks(scale, mainThreadFramesHeight);
708 this._context.restore();
709
710 var bottom = backgroundFramesHeight + 0.5;
711 this._context.strokeStyle = "rgba(120, 120, 120, 0.8)";
712 this._context.beginPath();
713 this._context.moveTo(0, bottom);
714 this._context.lineTo(this._canvas.width, bottom);
715 this._context.stroke();
716
717 if (backgroundVisibleFrames) {
718 const targetFPS = 30.0;
719 scale = (backgroundFramesHeight - this._topPadding) / (1.0 / targetF PS);
720 this._renderBars(backgroundVisibleFrames, scale, backgroundFramesHei ght);
721 }
685 }, 722 },
686 723
687 /** 724 /**
688 * @param {WebInspector.TimelineFrame} frame 725 * @param {WebInspector.TimelineFrame} frame
689 */ 726 */
690 addFrame: function(frame) 727 addFrame: function(frame)
691 { 728 {
692 this._frames.push(frame); 729 var frames;
730 if (frame.isBackground) {
731 frames = this._backgroundFrames;
732 } else {
733 frames = this._mainThreadFrames;
734 this._framesById[frame.id] = frame;
735 }
736 frames.push(frame);
693 }, 737 },
694 738
739 /**
740 * @param {number} x0
741 * @param {number} y0
742 * @param {number} width
743 * @param {number} height
744 */
745 _setCanvasWindow: function(x0, y0, width, height)
746 {
747 this._context.translate(x0, y0);
748 this._context.beginPath();
749 this._context.moveTo(0, 0);
750 this._context.lineTo(width, 0);
751 this._context.lineTo(width, height);
752 this._context.lineTo(0, height);
753 this._context.lineTo(0, 0);
754 this._context.clip();
755 },
695 756
696 /** 757 /**
697 * @param {Array.<WebInspector.TimelineFrame>} frames 758 * @param {Array.<WebInspector.TimelineFrame>} frames
698 * @param {number} framesPerBar 759 * @param {number} framesPerBar
699 * @return {Array.<WebInspector.TimelineFrame>} 760 * @return {Array.<WebInspector.TimelineFrame>}
700 */ 761 */
701 _aggregateFrames: function(frames, framesPerBar) 762 _aggregateFrames: function(frames, framesPerBar)
702 { 763 {
703 var visibleFrames = []; 764 var visibleFrames = [];
704 for (var barNumber = 0, currentFrame = 0; currentFrame < frames.length; ++barNumber) { 765 for (var barNumber = 0, currentFrame = 0; currentFrame < frames.length; ++barNumber) {
705 var barStartTime = frames[currentFrame].startTime; 766 var barStartTime = frames[currentFrame].startTime;
706 var longestFrame = null; 767 var longestFrame = null;
707 var longestDuration = 0; 768 var longestDuration = 0;
708 769
709 for (var lastFrame = Math.min(Math.floor((barNumber + 1) * framesPer Bar), frames.length); 770 for (var lastFrame = Math.min(Math.floor((barNumber + 1) * framesPer Bar), frames.length);
710 currentFrame < lastFrame; ++currentFrame) { 771 currentFrame < lastFrame; ++currentFrame) {
711 var duration = frames[currentFrame].duration; 772 var duration = this._frameDuration(frames[currentFrame]);
712 if (!longestFrame || longestDuration < duration) { 773 if (!longestFrame || longestDuration < duration) {
713 longestFrame = frames[currentFrame]; 774 longestFrame = frames[currentFrame];
714 longestDuration = duration; 775 longestDuration = duration;
715 } 776 }
716 } 777 }
717 var barEndTime = frames[currentFrame - 1].endTime; 778 var barEndTime = frames[currentFrame - 1].endTime;
718 if (longestFrame) { 779 if (longestFrame) {
719 visibleFrames.push(longestFrame); 780 visibleFrames.push(longestFrame);
720 this._barTimes.push({ startTime: barStartTime, endTime: barEndTi me }); 781 this._barTimes.push({ startTime: barStartTime, endTime: barEndTi me });
721 } 782 }
722 } 783 }
723 return visibleFrames; 784 return visibleFrames;
724 }, 785 },
725 786
726 /** 787 /**
788 * @param {WebInspector.TimelineFrame} frame
789 */
790 _frameDuration: function(frame)
791 {
792 var relatedFrame = frame.mainThreadFrameId && this._framesById[frame.mai nThreadFrameId];
793 return frame.duration + (relatedFrame ? relatedFrame.duration : 0);
794 },
795
796 /**
727 * @param {Array.<WebInspector.TimelineFrame>} frames 797 * @param {Array.<WebInspector.TimelineFrame>} frames
728 * @return {number} 798 * @return {number}
729 */ 799 */
730 _computeTargetFrameLength: function(frames) 800 _computeTargetFrameLength: function(frames)
731 { 801 {
732 var durations = frames.select("duration"); 802 var durations = [];
803 for (var i = 0; i < frames.length; ++i) {
804 if (frames[i])
805 durations.push(frames[i].duration);
806 }
733 var medianFrameLength = durations.qselect(Math.floor(durations.length / 2)); 807 var medianFrameLength = durations.qselect(Math.floor(durations.length / 2));
734 808
735 // Optimize appearance for 30fps. However, if at least half frames won't fit at this scale, 809 // Optimize appearance for 30fps. However, if at least half frames won't fit at this scale,
736 // fall back to using autoscale. 810 // fall back to using autoscale.
737 const targetFPS = 30; 811 const targetFPS = 30;
738 var result = 1.0 / targetFPS; 812 var result = 1.0 / targetFPS;
739 if (result >= medianFrameLength) 813 if (result >= medianFrameLength)
740 return result; 814 return result;
741 815
742 var maxFrameLength = Math.max.apply(Math, durations); 816 var maxFrameLength = Math.max.apply(Math, durations);
743 return Math.min(medianFrameLength * 2, maxFrameLength); 817 return Math.min(medianFrameLength * 2, maxFrameLength);
744 }, 818 },
745 819
746 /** 820 /**
747 * @param {Array.<WebInspector.TimelineFrame>} frames 821 * @param {Array.<WebInspector.TimelineFrame>} frames
748 * @param {number} scale 822 * @param {number} scale
749 * @param {number} windowHeight 823 * @param {number} windowHeight
750 */ 824 */
751 _renderBars: function(frames, scale, windowHeight) 825 _renderBars: function(frames, scale, windowHeight)
752 { 826 {
753 const maxPadding = 5 * window.devicePixelRatio; 827 const maxPadding = 5 * window.devicePixelRatio;
754 this._actualOuterBarWidth = Math.min((this._canvas.width - 2 * this._out erPadding) / frames.length, this._maxInnerBarWidth + maxPadding); 828 this._actualOuterBarWidth = Math.min((this._canvas.width - 2 * this._out erPadding) / frames.length, this._maxInnerBarWidth + maxPadding);
755 this._actualPadding = Math.min(Math.floor(this._actualOuterBarWidth / 3) , maxPadding); 829 this._actualPadding = Math.min(Math.floor(this._actualOuterBarWidth / 3) , maxPadding);
756 830
757 var barWidth = this._actualOuterBarWidth - this._actualPadding; 831 var barWidth = this._actualOuterBarWidth - this._actualPadding;
758 for (var i = 0; i < frames.length; ++i) 832 for (var i = 0; i < frames.length; ++i) {
759 this._renderBar(this._barNumberToScreenPosition(i), barWidth, window Height, frames[i], scale); 833 if (frames[i])
834 this._renderBar(this._barNumberToScreenPosition(i), barWidth, wi ndowHeight, frames[i], scale);
835 }
760 }, 836 },
761 837
762 /** 838 /**
763 * @param {number} n 839 * @param {number} n
764 */ 840 */
765 _barNumberToScreenPosition: function(n) 841 _barNumberToScreenPosition: function(n)
766 { 842 {
767 return this._outerPadding + this._actualOuterBarWidth * n; 843 return this._outerPadding + this._actualOuterBarWidth * n;
768 }, 844 },
769 845
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
803 879
804 this._context.moveTo(0, y); 880 this._context.moveTo(0, y);
805 this._context.lineTo(this._canvas.width, y); 881 this._context.lineTo(this._canvas.width, y);
806 882
807 this._context.fillStyle = "rgba(255, 255, 255, 0.5)"; 883 this._context.fillStyle = "rgba(255, 255, 255, 0.5)";
808 this._context.fillRect(labelX - labelWidth, labelY, labelWidth, line Height); 884 this._context.fillRect(labelX - labelWidth, labelY, labelWidth, line Height);
809 this._context.fillStyle = "black"; 885 this._context.fillStyle = "black";
810 this._context.fillText(label, labelX - labelPadding, labelY + lineHe ight - baselineHeight); 886 this._context.fillText(label, labelX - labelPadding, labelY + lineHe ight - baselineHeight);
811 labelTopMargin = labelY + lineHeight; 887 labelTopMargin = labelY + lineHeight;
812 } 888 }
813 this._context.strokeStyle = "rgba(128, 128, 128, 0.5)"; 889 this._context.strokeStyle = "rgba(60, 60, 60, 0.4)";
814 this._context.stroke(); 890 this._context.stroke();
815 this._context.restore(); 891 this._context.restore();
816 }, 892 },
817 893
818 /** 894 /**
819 * @param {number} left 895 * @param {number} left
820 * @param {number} width 896 * @param {number} width
821 * @param {number} windowHeight 897 * @param {number} windowHeight
822 * @param {WebInspector.TimelineFrame} frame 898 * @param {WebInspector.TimelineFrame} frame
823 * @param {number} scale 899 * @param {number} scale
824 */ 900 */
825 _renderBar: function(left, width, windowHeight, frame, scale) 901 _renderBar: function(left, width, windowHeight, frame, scale)
826 { 902 {
827 var categories = Object.keys(WebInspector.TimelinePresentationModel.cate gories()); 903 var categories = Object.keys(WebInspector.TimelinePresentationModel.cate gories());
828 if (!categories.length) 904 if (!categories.length)
829 return; 905 return;
830 var x = Math.floor(left) + 0.5; 906 var x = Math.floor(left) + 0.5;
831 width = Math.floor(width); 907 width = Math.floor(width);
832 908
833 for (var i = 0, bottomOffset = windowHeight; i < categories.length; ++i) { 909 for (var i = 0, bottomOffset = windowHeight; i < categories.length; ++i) {
834 var category = categories[i]; 910 var category = categories[i];
835 var duration = frame.timeByCategory[category]; 911 var duration = frame.timeByCategory[category];
836 912
837 if (!duration) 913 if (!duration)
838 continue; 914 continue;
839 var height = duration * scale; 915 var height = Math.round(duration * scale);
840 var y = Math.floor(bottomOffset - height) + 0.5; 916 var y = Math.floor(bottomOffset - height) + 0.5;
841 917
842 this._context.save(); 918 this._context.save();
843 this._context.translate(x, 0); 919 this._context.translate(x, 0);
844 this._context.scale(width / this._maxInnerBarWidth, 1); 920 this._context.scale(width / this._maxInnerBarWidth, 1);
845 this._context.fillStyle = this._fillStyles[category]; 921 this._context.fillStyle = this._fillStyles[category];
846 this._context.fillRect(0, y, this._maxInnerBarWidth, Math.floor(heig ht)); 922 this._context.fillRect(0, y, this._maxInnerBarWidth, Math.floor(heig ht));
847 this._context.strokeStyle = WebInspector.TimelinePresentationModel.c ategories()[category].borderColor; 923 this._context.strokeStyle = WebInspector.TimelinePresentationModel.c ategories()[category].borderColor;
848 this._context.beginPath(); 924 this._context.beginPath();
849 this._context.moveTo(0, y); 925 this._context.moveTo(0, y);
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
961 WebInspector.TimelineWindowFilter.prototype = { 1037 WebInspector.TimelineWindowFilter.prototype = {
962 /** 1038 /**
963 * @param {!WebInspector.TimelinePresentationModel.Record} record 1039 * @param {!WebInspector.TimelinePresentationModel.Record} record
964 * @return {boolean} 1040 * @return {boolean}
965 */ 1041 */
966 accept: function(record) 1042 accept: function(record)
967 { 1043 {
968 return record.lastChildEndTime >= this._pane._windowStartTime && record. startTime <= this._pane._windowEndTime; 1044 return record.lastChildEndTime >= this._pane._windowStartTime && record. startTime <= this._pane._windowEndTime;
969 } 1045 }
970 } 1046 }
OLDNEW
« no previous file with comments | « Source/devtools/front_end/TimelineModel.js ('k') | Source/devtools/front_end/TimelinePresentationModel.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698