OLD | NEW |
---|---|
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 624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
635 * @param {WebInspector.TimelineModel} model | 635 * @param {WebInspector.TimelineModel} model |
636 */ | 636 */ |
637 WebInspector.TimelineFrameOverview = function(model) | 637 WebInspector.TimelineFrameOverview = function(model) |
638 { | 638 { |
639 WebInspector.TimelineOverviewBase.call(this, model); | 639 WebInspector.TimelineOverviewBase.call(this, model); |
640 this.element.id = "timeline-overview-frames"; | 640 this.element.id = "timeline-overview-frames"; |
641 this.reset(); | 641 this.reset(); |
642 | 642 |
643 this._outerPadding = 4 * window.devicePixelRatio; | 643 this._outerPadding = 4 * window.devicePixelRatio; |
644 this._maxInnerBarWidth = 10 * window.devicePixelRatio; | 644 this._maxInnerBarWidth = 10 * window.devicePixelRatio; |
645 this._topPadding = 6 * window.devicePixelRatio; | |
645 | 646 |
646 // The below two are really computed by update() -- but let's have something so that windowTimes() is happy. | 647 // The below two are really computed by update() -- but let's have something so that windowTimes() is happy. |
647 this._actualPadding = 5 * window.devicePixelRatio; | 648 this._actualPadding = 5 * window.devicePixelRatio; |
648 this._actualOuterBarWidth = this._maxInnerBarWidth + this._actualPadding; | 649 this._actualOuterBarWidth = this._maxInnerBarWidth + this._actualPadding; |
649 | 650 |
650 this._fillStyles = {}; | 651 this._fillStyles = {}; |
651 var categories = WebInspector.TimelinePresentationModel.categories(); | 652 var categories = WebInspector.TimelinePresentationModel.categories(); |
652 for (var category in categories) | 653 for (var category in categories) |
653 this._fillStyles[category] = WebInspector.TimelinePresentationModel.crea teFillStyleForCategory(this._context, this._maxInnerBarWidth, 0, categories[cate gory]); | 654 this._fillStyles[category] = WebInspector.TimelinePresentationModel.crea teFillStyleForCategory(this._context, this._maxInnerBarWidth, 0, categories[cate gory]); |
655 this._frameTopShadeGradient = this._context.createLinearGradient(0, 0, 0, th is._topPadding); | |
656 this._frameTopShadeGradient.addColorStop(0, "rgba(255, 255, 255, 0.9)"); | |
657 this._frameTopShadeGradient.addColorStop(1, "rgba(255, 255, 255, 0.2)"); | |
654 } | 658 } |
655 | 659 |
656 WebInspector.TimelineFrameOverview.prototype = { | 660 WebInspector.TimelineFrameOverview.prototype = { |
657 reset: function() | 661 reset: function() |
658 { | 662 { |
659 this._recordsPerBar = 1; | 663 this._recordsPerBar = 1; |
660 /** @type {!Array.<{startTime:number, endTime:number}>} */ | 664 /** @type {!Array.<{startTime:number, endTime:number}>} */ |
661 this._barTimes = []; | 665 this._barTimes = []; |
662 this._frames = []; | 666 this._mainThreadFrames = []; |
667 this._backgroundFrames = []; | |
668 this._framesById = {}; | |
663 }, | 669 }, |
664 | 670 |
665 update: function() | 671 update: function() |
666 { | 672 { |
667 this._resetCanvas(); | 673 this._resetCanvas(); |
668 this._barTimes = []; | 674 this._barTimes = []; |
669 | 675 |
676 var backgroundFramesHeight = 15; | |
677 var mainThreadFramesHeight = this._canvas.height - backgroundFramesHeigh t; | |
670 const minBarWidth = 4 * window.devicePixelRatio; | 678 const minBarWidth = 4 * window.devicePixelRatio; |
671 var frameCount = this._frames.length; | 679 var frameCount = Math.max(this._mainThreadFrames.length, this._backgroun dFrames.length); |
pfeldman
2013/11/06 17:21:05
this._backgroundFrames.length || this._mainThreadF
| |
672 var framesPerBar = Math.max(1, frameCount * minBarWidth / this._canvas.w idth); | 680 var framesPerBar = Math.max(1, frameCount * minBarWidth / this._canvas.w idth); |
673 var visibleFrames = this._aggregateFrames(this._frames, framesPerBar); | 681 |
674 var windowHeight = this._canvas.height; | 682 var mainThreadVisibleFrames; |
675 const paddingTop = 4 * window.devicePixelRatio; | 683 var backgroundVisibleFrames; |
676 var scale = (windowHeight - paddingTop) / this._computeTargetFrameLength (visibleFrames); | 684 if (this._backgroundFrames.length) { |
677 this._renderBars(visibleFrames, scale, windowHeight); | 685 backgroundVisibleFrames = this._aggregateFrames(this._backgroundFram es, framesPerBar); |
678 this._drawFPSMarks(scale, windowHeight); | 686 mainThreadVisibleFrames = Array(backgroundVisibleFrames.length); |
pfeldman
2013/11/06 17:21:05
This can not compile - new Array.
| |
687 for (var i = 0; i < backgroundVisibleFrames.length; ++i) { | |
688 var frameId = backgroundVisibleFrames[i].mainThreadFrameId; | |
689 mainThreadVisibleFrames[i] = frameId && this._framesById[frameId ]; | |
690 } | |
691 } else { | |
692 mainThreadVisibleFrames = this._aggregateFrames(this._mainThreadFram es, framesPerBar); | |
693 } | |
694 | |
695 this._context.save(); | |
696 this._setCanvasWindow(0, backgroundFramesHeight, this._canvas.width, mai nThreadFramesHeight); | |
697 var scale = (mainThreadFramesHeight - this._topPadding) / this._computeT argetFrameLength(mainThreadVisibleFrames); | |
698 this._renderBars(mainThreadVisibleFrames, scale, mainThreadFramesHeight) ; | |
699 this._context.fillStyle = this._frameTopShadeGradient; | |
700 this._context.fillRect(0, 0, this._canvas.width, this._topPadding); | |
701 this._drawFPSMarks(scale, mainThreadFramesHeight); | |
702 this._context.restore(); | |
703 | |
704 var bottom = backgroundFramesHeight + 0.5; | |
705 this._context.strokeStyle = "rgba(120, 120, 120, 0.8)"; | |
706 this._context.beginPath(); | |
707 this._context.moveTo(0, bottom); | |
708 this._context.lineTo(this._canvas.width, bottom); | |
709 this._context.stroke(); | |
710 | |
711 if (backgroundVisibleFrames) { | |
712 const targetFPS = 30.0; | |
713 scale = (backgroundFramesHeight - this._topPadding) / (1.0 / targetF PS); | |
714 this._renderBars(backgroundVisibleFrames, scale, backgroundFramesHei ght); | |
715 } | |
679 }, | 716 }, |
680 | 717 |
681 /** | 718 /** |
682 * @param {WebInspector.TimelineFrame} frame | 719 * @param {WebInspector.TimelineFrame} frame |
683 */ | 720 */ |
684 addFrame: function(frame) | 721 addFrame: function(frame) |
685 { | 722 { |
686 this._frames.push(frame); | 723 var frames; |
724 if (frame.isBackground) { | |
725 frames = this._backgroundFrames; | |
726 } else { | |
727 frames = this._mainThreadFrames; | |
728 this._framesById[frame.id] = frame; | |
729 } | |
730 frames.push(frame); | |
687 }, | 731 }, |
688 | 732 |
733 /** | |
734 * @param {number} x0 | |
735 * @param {number} y0 | |
736 * @param {number} width | |
737 * @param {number} height | |
738 */ | |
739 _setCanvasWindow: function(x0, y0, width, height) | |
740 { | |
741 this._context.translate(x0, y0); | |
742 this._context.beginPath(); | |
743 this._context.moveTo(0, 0); | |
744 this._context.lineTo(width, 0); | |
745 this._context.lineTo(width, height); | |
746 this._context.lineTo(0, height); | |
747 this._context.lineTo(0, 0); | |
748 this._context.clip(); | |
749 }, | |
689 | 750 |
690 /** | 751 /** |
691 * @param {Array.<WebInspector.TimelineFrame>} frames | 752 * @param {Array.<WebInspector.TimelineFrame>} frames |
692 * @param {number} framesPerBar | 753 * @param {number} framesPerBar |
693 * @return {Array.<WebInspector.TimelineFrame>} | 754 * @return {Array.<WebInspector.TimelineFrame>} |
694 */ | 755 */ |
695 _aggregateFrames: function(frames, framesPerBar) | 756 _aggregateFrames: function(frames, framesPerBar) |
696 { | 757 { |
697 var visibleFrames = []; | 758 var visibleFrames = []; |
698 for (var barNumber = 0, currentFrame = 0; currentFrame < frames.length; ++barNumber) { | 759 for (var barNumber = 0, currentFrame = 0; currentFrame < frames.length; ++barNumber) { |
699 var barStartTime = frames[currentFrame].startTime; | 760 var barStartTime = frames[currentFrame].startTime; |
700 var longestFrame = null; | 761 var longestFrame = null; |
701 var longestDuration = 0; | 762 var longestDuration = 0; |
702 | 763 |
703 for (var lastFrame = Math.min(Math.floor((barNumber + 1) * framesPer Bar), frames.length); | 764 for (var lastFrame = Math.min(Math.floor((barNumber + 1) * framesPer Bar), frames.length); |
704 currentFrame < lastFrame; ++currentFrame) { | 765 currentFrame < lastFrame; ++currentFrame) { |
705 var duration = frames[currentFrame].duration; | 766 var duration = this._frameDuration(frames[currentFrame]); |
706 if (!longestFrame || longestDuration < duration) { | 767 if (!longestFrame || longestDuration < duration) { |
707 longestFrame = frames[currentFrame]; | 768 longestFrame = frames[currentFrame]; |
708 longestDuration = duration; | 769 longestDuration = duration; |
709 } | 770 } |
710 } | 771 } |
711 var barEndTime = frames[currentFrame - 1].endTime; | 772 var barEndTime = frames[currentFrame - 1].endTime; |
712 if (longestFrame) { | 773 if (longestFrame) { |
713 visibleFrames.push(longestFrame); | 774 visibleFrames.push(longestFrame); |
714 this._barTimes.push({ startTime: barStartTime, endTime: barEndTi me }); | 775 this._barTimes.push({ startTime: barStartTime, endTime: barEndTi me }); |
715 } | 776 } |
716 } | 777 } |
717 return visibleFrames; | 778 return visibleFrames; |
718 }, | 779 }, |
719 | 780 |
720 /** | 781 /** |
782 * @param {WebInspector.TimelineFrame} frame | |
783 */ | |
784 _frameDuration: function(frame) | |
785 { | |
786 var relatedFrame = frame.mainThreadFrameId && this._framesById[frame.mai nThreadFrameId]; | |
787 return frame.duration + (relatedFrame ? relatedFrame.duration : 0); | |
788 }, | |
789 | |
790 /** | |
721 * @param {Array.<WebInspector.TimelineFrame>} frames | 791 * @param {Array.<WebInspector.TimelineFrame>} frames |
722 * @return {number} | 792 * @return {number} |
723 */ | 793 */ |
724 _computeTargetFrameLength: function(frames) | 794 _computeTargetFrameLength: function(frames) |
725 { | 795 { |
726 var durations = frames.select("duration"); | 796 var durations = []; |
797 for (var i = 0; i < frames.length; ++i) { | |
798 if (frames[i]) | |
799 durations.push(frames[i].duration); | |
800 } | |
727 var medianFrameLength = durations.qselect(Math.floor(durations.length / 2)); | 801 var medianFrameLength = durations.qselect(Math.floor(durations.length / 2)); |
728 | 802 |
729 // Optimize appearance for 30fps. However, if at least half frames won't fit at this scale, | 803 // Optimize appearance for 30fps. However, if at least half frames won't fit at this scale, |
730 // fall back to using autoscale. | 804 // fall back to using autoscale. |
731 const targetFPS = 30; | 805 const targetFPS = 30; |
732 var result = 1.0 / targetFPS; | 806 var result = 1.0 / targetFPS; |
733 if (result >= medianFrameLength) | 807 if (result >= medianFrameLength) |
734 return result; | 808 return result; |
735 | 809 |
736 var maxFrameLength = Math.max.apply(Math, durations); | 810 var maxFrameLength = Math.max.apply(Math, durations); |
737 return Math.min(medianFrameLength * 2, maxFrameLength); | 811 return Math.min(medianFrameLength * 2, maxFrameLength); |
738 }, | 812 }, |
739 | 813 |
740 /** | 814 /** |
741 * @param {Array.<WebInspector.TimelineFrame>} frames | 815 * @param {Array.<WebInspector.TimelineFrame>} frames |
742 * @param {number} scale | 816 * @param {number} scale |
743 * @param {number} windowHeight | 817 * @param {number} windowHeight |
744 */ | 818 */ |
745 _renderBars: function(frames, scale, windowHeight) | 819 _renderBars: function(frames, scale, windowHeight) |
746 { | 820 { |
747 const maxPadding = 5 * window.devicePixelRatio; | 821 const maxPadding = 5 * window.devicePixelRatio; |
748 this._actualOuterBarWidth = Math.min((this._canvas.width - 2 * this._out erPadding) / frames.length, this._maxInnerBarWidth + maxPadding); | 822 this._actualOuterBarWidth = Math.min((this._canvas.width - 2 * this._out erPadding) / frames.length, this._maxInnerBarWidth + maxPadding); |
749 this._actualPadding = Math.min(Math.floor(this._actualOuterBarWidth / 3) , maxPadding); | 823 this._actualPadding = Math.min(Math.floor(this._actualOuterBarWidth / 3) , maxPadding); |
750 | 824 |
751 var barWidth = this._actualOuterBarWidth - this._actualPadding; | 825 var barWidth = this._actualOuterBarWidth - this._actualPadding; |
752 for (var i = 0; i < frames.length; ++i) | 826 for (var i = 0; i < frames.length; ++i) { |
753 this._renderBar(this._barNumberToScreenPosition(i), barWidth, window Height, frames[i], scale); | 827 if (frames[i]) |
828 this._renderBar(this._barNumberToScreenPosition(i), barWidth, wi ndowHeight, frames[i], scale); | |
829 } | |
754 }, | 830 }, |
755 | 831 |
756 /** | 832 /** |
757 * @param {number} n | 833 * @param {number} n |
758 */ | 834 */ |
759 _barNumberToScreenPosition: function(n) | 835 _barNumberToScreenPosition: function(n) |
760 { | 836 { |
761 return this._outerPadding + this._actualOuterBarWidth * n; | 837 return this._outerPadding + this._actualOuterBarWidth * n; |
762 }, | 838 }, |
763 | 839 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
797 | 873 |
798 this._context.moveTo(0, y); | 874 this._context.moveTo(0, y); |
799 this._context.lineTo(this._canvas.width, y); | 875 this._context.lineTo(this._canvas.width, y); |
800 | 876 |
801 this._context.fillStyle = "rgba(255, 255, 255, 0.5)"; | 877 this._context.fillStyle = "rgba(255, 255, 255, 0.5)"; |
802 this._context.fillRect(labelX - labelWidth, labelY, labelWidth, line Height); | 878 this._context.fillRect(labelX - labelWidth, labelY, labelWidth, line Height); |
803 this._context.fillStyle = "black"; | 879 this._context.fillStyle = "black"; |
804 this._context.fillText(label, labelX - labelPadding, labelY + lineHe ight - baselineHeight); | 880 this._context.fillText(label, labelX - labelPadding, labelY + lineHe ight - baselineHeight); |
805 labelTopMargin = labelY + lineHeight; | 881 labelTopMargin = labelY + lineHeight; |
806 } | 882 } |
807 this._context.strokeStyle = "rgba(128, 128, 128, 0.5)"; | 883 this._context.strokeStyle = "rgba(60, 60, 60, 0.4)"; |
808 this._context.stroke(); | 884 this._context.stroke(); |
809 this._context.restore(); | 885 this._context.restore(); |
810 }, | 886 }, |
811 | 887 |
812 /** | 888 /** |
813 * @param {number} left | 889 * @param {number} left |
814 * @param {number} width | 890 * @param {number} width |
815 * @param {number} windowHeight | 891 * @param {number} windowHeight |
816 * @param {WebInspector.TimelineFrame} frame | 892 * @param {WebInspector.TimelineFrame} frame |
817 * @param {number} scale | 893 * @param {number} scale |
818 */ | 894 */ |
819 _renderBar: function(left, width, windowHeight, frame, scale) | 895 _renderBar: function(left, width, windowHeight, frame, scale) |
820 { | 896 { |
821 var categories = Object.keys(WebInspector.TimelinePresentationModel.cate gories()); | 897 var categories = Object.keys(WebInspector.TimelinePresentationModel.cate gories()); |
822 if (!categories.length) | 898 if (!categories.length) |
823 return; | 899 return; |
824 var x = Math.floor(left) + 0.5; | 900 var x = Math.floor(left) + 0.5; |
825 width = Math.floor(width); | 901 width = Math.floor(width); |
826 | 902 |
827 for (var i = 0, bottomOffset = windowHeight; i < categories.length; ++i) { | 903 for (var i = 0, bottomOffset = windowHeight; i < categories.length; ++i) { |
828 var category = categories[i]; | 904 var category = categories[i]; |
829 var duration = frame.timeByCategory[category]; | 905 var duration = frame.timeByCategory[category]; |
830 | 906 |
831 if (!duration) | 907 if (!duration) |
832 continue; | 908 continue; |
833 var height = duration * scale; | 909 var height = Math.round(duration * scale); |
834 var y = Math.floor(bottomOffset - height) + 0.5; | 910 var y = Math.floor(bottomOffset - height) + 0.5; |
835 | 911 |
836 this._context.save(); | 912 this._context.save(); |
837 this._context.translate(x, 0); | 913 this._context.translate(x, 0); |
838 this._context.scale(width / this._maxInnerBarWidth, 1); | 914 this._context.scale(width / this._maxInnerBarWidth, 1); |
839 this._context.fillStyle = this._fillStyles[category]; | 915 this._context.fillStyle = this._fillStyles[category]; |
840 this._context.fillRect(0, y, this._maxInnerBarWidth, Math.floor(heig ht)); | 916 this._context.fillRect(0, y, this._maxInnerBarWidth, Math.floor(heig ht)); |
841 this._context.strokeStyle = WebInspector.TimelinePresentationModel.c ategories()[category].borderColor; | 917 this._context.strokeStyle = WebInspector.TimelinePresentationModel.c ategories()[category].borderColor; |
842 this._context.beginPath(); | 918 this._context.beginPath(); |
843 this._context.moveTo(0, y); | 919 this._context.moveTo(0, y); |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
955 WebInspector.TimelineWindowFilter.prototype = { | 1031 WebInspector.TimelineWindowFilter.prototype = { |
956 /** | 1032 /** |
957 * @param {!WebInspector.TimelinePresentationModel.Record} record | 1033 * @param {!WebInspector.TimelinePresentationModel.Record} record |
958 * @return {boolean} | 1034 * @return {boolean} |
959 */ | 1035 */ |
960 accept: function(record) | 1036 accept: function(record) |
961 { | 1037 { |
962 return record.lastChildEndTime >= this._pane._windowStartTime && record. startTime <= this._pane._windowEndTime; | 1038 return record.lastChildEndTime >= this._pane._windowStartTime && record. startTime <= this._pane._windowEndTime; |
963 } | 1039 } |
964 } | 1040 } |
OLD | NEW |