@yuebai008/cli
Version:
Command line interface for rapid qg-minigame development
1 lines • 5.94 kB
JavaScript
import*as Common from"../../core/common/common.js";import*as i18n from"../../core/i18n/i18n.js";import*as Platform from"../../core/platform/platform.js";import*as PerfUI from"../../ui/legacy/components/perf_ui/perf_ui.js";import*as UI from"../../ui/legacy/legacy.js";export class HeapTimelineOverview extends(Common.ObjectWrapper.eventMixin(UI.Widget.VBox)){overviewCalculator;overviewContainer;overviewGrid;overviewCanvas;windowLeft;windowRight;yScale;xScale;profileSamples;running;updateOverviewCanvas;updateGridTimerId;updateTimerId;windowWidth;constructor(){super(),this.element.id="heap-recording-view",this.element.classList.add("heap-tracking-overview"),this.overviewCalculator=new OverviewCalculator,this.overviewContainer=this.element.createChild("div","heap-overview-container"),this.overviewGrid=new PerfUI.OverviewGrid.OverviewGrid("heap-recording",this.overviewCalculator),this.overviewGrid.element.classList.add("fill"),this.overviewCanvas=this.overviewContainer.createChild("canvas","heap-recording-overview-canvas"),this.overviewContainer.appendChild(this.overviewGrid.element),this.overviewGrid.addEventListener(PerfUI.OverviewGrid.Events.WindowChanged,this.onWindowChanged,this),this.windowLeft=0,this.windowRight=1,this.overviewGrid.setWindow(this.windowLeft,this.windowRight),this.yScale=new SmoothScale,this.xScale=new SmoothScale,this.profileSamples=new Samples}start(){this.running=!0;const e=()=>{this.update(),this.running&&this.element.window().requestAnimationFrame(e)};e()}stop(){this.running=!1}setSamples(e){this.profileSamples=e,this.running||this.update()}drawOverviewCanvas(e,i){if(!this.profileSamples)return;const t=this.profileSamples,s=t.sizes,a=t.max,o=t.timestamps,r=o[0],n=this.xScale.nextScale(e/t.totalTime);let l=0;function h(e,i){let t=0,s=0;for(let a=1;a<o.length;++a){const l=Math.floor((o[a]-r)*n);l!==s&&(t&&i(s,t),t=0,s=l),t+=e[a]}i(s,t)}h(s,(function(e,i){l=Math.max(l,i)}));const d=this.yScale.nextScale(l?i/(1.1*l):0);this.overviewCanvas.width=e*window.devicePixelRatio,this.overviewCanvas.height=i*window.devicePixelRatio,this.overviewCanvas.style.width=e+"px",this.overviewCanvas.style.height=i+"px";const m=this.overviewCanvas.getContext("2d");if(!m)throw new Error("Failed to get canvas context");const u=m;if(u.scale(window.devicePixelRatio,window.devicePixelRatio),this.running){u.beginPath(),u.lineWidth=2,u.strokeStyle="rgba(192, 192, 192, 0.6)";const e=(Date.now()-r)*n;u.moveTo(e,i-1),u.lineTo(e,0),u.stroke(),u.closePath()}let c,w=0;if(d){const t=(i-14)/d;c=Math.pow(1024,Math.floor(Math.log(t)/Math.log(1024))),c*=Math.pow(10,Math.floor(Math.log(t/c)/Math.LN10)),5*c<=t&&(c*=5),w=Math.round(i-c*d-.5)+.5,u.beginPath(),u.lineWidth=1,u.strokeStyle="rgba(0, 0, 0, 0.2)",u.moveTo(0,w),u.lineTo(e,w),u.stroke(),u.closePath()}function v(e,t){u.moveTo(e,i-1),u.lineTo(e,Math.round(i-t*d-1))}if(u.beginPath(),u.lineWidth=2,u.strokeStyle="rgba(192, 192, 192, 0.6)",h(a,v),u.stroke(),u.closePath(),u.beginPath(),u.lineWidth=2,u.strokeStyle="rgba(0, 0, 192, 0.8)",h(s,v),u.stroke(),u.closePath(),c){const e=Platform.NumberUtilities.bytesToString(c),i=4,t=0,s=w-.5,a=2*i+u.measureText(e).width;u.beginPath(),u.textBaseline="bottom",u.font="10px "+window.getComputedStyle(this.element,null).getPropertyValue("font-family"),u.fillStyle="rgba(255, 255, 255, 0.75)",u.fillRect(t,s-14,a,14),u.fillStyle="rgb(64, 64, 64)",u.fillText(e,t+i,s),u.fill(),u.closePath()}}onResize(){this.updateOverviewCanvas=!0,this.scheduleUpdate()}onWindowChanged(){this.updateGridTimerId||(this.updateGridTimerId=window.setTimeout(this.updateGrid.bind(this),10))}scheduleUpdate(){this.updateTimerId||(this.updateTimerId=window.setTimeout(this.update.bind(this),10))}updateBoundaries(){this.windowLeft=this.overviewGrid.windowLeft(),this.windowRight=this.overviewGrid.windowRight(),this.windowWidth=this.windowRight-this.windowLeft}update(){this.updateTimerId=null,this.isShowing()&&(this.updateBoundaries(),this.overviewCalculator.updateBoundaries(this),this.overviewGrid.updateDividers(this.overviewCalculator),this.drawOverviewCanvas(this.overviewContainer.clientWidth,this.overviewContainer.clientHeight-20))}updateGrid(){this.updateGridTimerId=0,this.updateBoundaries();const e=this.profileSamples.ids;if(!e.length)return;const i=this.profileSamples.timestamps,t=this.profileSamples.sizes,s=i[0],a=this.profileSamples.totalTime,o=s+a*this.windowLeft,r=s+a*this.windowRight,n=Platform.ArrayUtilities.lowerBound(i,o,Platform.ArrayUtilities.DEFAULT_COMPARATOR),l=Platform.ArrayUtilities.upperBound(i,r,Platform.ArrayUtilities.DEFAULT_COMPARATOR);let h=0;for(let e=n;e<l;++e)h+=t[e];const d=n>0?e[n-1]:0,m=l<e.length?e[l]:1/0;this.dispatchEventToListeners("IdsRangeChanged",{minId:d,maxId:m,size:h})}}export class SmoothScale{lastUpdate;currentScale;constructor(){this.lastUpdate=0,this.currentScale=0}nextScale(e){if(e=e||this.currentScale,this.currentScale){const i=Date.now(),t=i-this.lastUpdate;this.lastUpdate=i;const s=20,a=Math.pow(s,t/1e3),o=e/this.currentScale;this.currentScale*=Platform.NumberUtilities.clamp(o,1/a,a)}else this.currentScale=e;return this.currentScale}}export class Samples{sizes;ids;timestamps;max;totalTime;constructor(){this.sizes=[],this.ids=[],this.timestamps=[],this.max=[],this.totalTime=3e4}}export class OverviewCalculator{maximumBoundaries;minimumBoundaries;xScaleFactor;constructor(){this.maximumBoundaries=0,this.minimumBoundaries=0,this.xScaleFactor=0}updateBoundaries(e){this.minimumBoundaries=0,this.maximumBoundaries=e.profileSamples.totalTime,this.xScaleFactor=e.overviewContainer.clientWidth/this.maximumBoundaries}computePosition(e){return(e-this.minimumBoundaries)*this.xScaleFactor}formatValue(e,i){return i18n.TimeUtilities.secondsToString(e/1e3,Boolean(i))}maximumBoundary(){return this.maximumBoundaries}minimumBoundary(){return this.minimumBoundaries}zeroTime(){return this.minimumBoundaries}boundarySpan(){return this.maximumBoundaries-this.minimumBoundaries}}