@yuebai008/cli
Version:
Command line interface for rapid qg-minigame development
1 lines • 9.7 kB
JavaScript
import*as i18n from"../../core/i18n/i18n.js";import*as Platform from"../../core/platform/platform.js";import*as TimelineModel from"../../models/timeline_model/timeline_model.js";import*as TraceEngine from"../../models/trace/trace.js";import*as PerfUI from"../../ui/legacy/components/perf_ui/perf_ui.js";import*as UI from"../../ui/legacy/legacy.js";import{TimelineUIUtils}from"./TimelineUIUtils.js";const UIStrings={net:"NET",cpu:"CPU",heap:"HEAP",sSDash:"{PH1} – {PH2}"},str_=i18n.i18n.registerUIStrings("panels/timeline/TimelineEventOverview.ts",UIStrings),i18nString=i18n.i18n.getLocalizedString.bind(void 0,str_);export class TimelineEventOverview extends PerfUI.TimelineOverviewPane.TimelineOverviewBase{constructor(e,t){super(),this.element.id="timeline-overview-"+e,this.element.classList.add("overview-strip"),t&&(this.element.createChild("div","timeline-overview-strip-title").textContent=t)}renderBar(e,t,i,n,r){const s=e,a=t-e,o=this.context();o.fillStyle=r,o.fillRect(s,i,a,n)}}const HIGH_NETWORK_PRIORITIES=new Set(["VeryHigh","High","Medium"]);export class TimelineEventOverviewNetwork extends TimelineEventOverview{#e;constructor(e){super("network",i18nString(UIStrings.net)),this.#e=e}update(){super.update(),this.#t()}#t(){if(!this.#e)return;const e=TraceEngine.Helpers.Timing.traceBoundsMilliseconds(this.#e.Meta.traceBounds),t=this.height()/2,i=this.width(),n=i/e.range,r=new Path2D,s=new Path2D;for(const a of this.#e.NetworkRequests.byTime){const o=HIGH_NETWORK_PRIORITIES.has(a.args.data.priority)?r:s,{startTime:l,endTime:c}=TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(a),m=Math.max(Math.floor((l-e.min)*n),0),h=Math.min(Math.ceil((c-e.min)*n+1),i);o.rect(m,0,h-m,t-1)}const a=this.context();a.save(),a.fillStyle="hsl(214, 60%, 60%)",a.fill(r),a.translate(0,t),a.fillStyle="hsl(214, 80%, 80%)",a.fill(s),a.restore()}}const categoryToIndex=new WeakMap;export class TimelineEventOverviewCPUActivity extends TimelineEventOverview{backgroundCanvas;#i=null;constructor(e){super("cpu-activity",i18nString(UIStrings.cpu)),this.#i=e,this.backgroundCanvas=this.element.createChild("canvas","fill background")}resetCanvas(){super.resetCanvas(),this.backgroundCanvas.width=this.element.clientWidth*window.devicePixelRatio,this.backgroundCanvas.height=this.element.clientHeight*window.devicePixelRatio}update(){if(super.update(),!this.#i)return;const e=this.#i.timelineModel(),t=4*window.devicePixelRatio,i=this.width(),n=this.height(),r=n,s=e.minimumRecordTime(),a=e.maximumRecordTime()-s,o=t/(i/a),l=TimelineUIUtils.categories(),c=TimelineUIUtils.getTimelineMainEventCategories(),m=c.indexOf("other");console.assert(0===c.indexOf("idle"));for(let e=0;e<c.length;++e)categoryToIndex.set(l[c[e]],e);const h=this.backgroundCanvas.getContext("2d");if(!h)throw new Error("Could not find 2d canvas");for(const t of e.tracks())t.type===TimelineModel.TimelineModel.TrackType.MainThread&&t.forMainFrame?d(this.context(),t.events):d(h,t.events);function d(e,h){const d=new Quantizer(s,o,(function(e){let i=r;for(let r=1;r<c.length;++r){i-=(e[r]||0)/o*n,g[r].bezierCurveTo(u,T[r],u,i,u+t/2,i),T[r]=i}u+=t}));let u=0;const p=[],g=[],T=[];for(let e=0;e<c.length;++e)g[e]=new Path2D,g[e].moveTo(0,n),T[e]=n;TimelineModel.TimelineModel.TimelineModelImpl.forEachEvent(h,(function(e){const{startTime:t}=TraceEngine.Legacy.timesForEventInMilliseconds(e),i=p.length?p[p.length-1]:0;d.appendInterval(t,i);const n=categoryToIndex.get(TimelineUIUtils.eventStyle(e).category);0!==n&&p.push(void 0!==n?n:m)}),(function(e){const{endTime:t}=TraceEngine.Legacy.timesForEventInMilliseconds(e),i=p.pop();void 0!==t&&i&&d.appendInterval(t,i)})),d.appendInterval(s+a+o,0);for(let t=c.length-1;t>0;--t)g[t].lineTo(i,n),e.fillStyle=l[c[t]].color,e.fill(g[t])}!function(e){const t=4*window.devicePixelRatio;e.save(),e.lineWidth=t/Math.sqrt(8);for(let r=.5;r<i+n;r+=t)e.moveTo(r,0),e.lineTo(r-n,n);e.globalCompositeOperation="destination-out",e.stroke(),e.restore()}(h)}}export class TimelineEventOverviewResponsiveness extends TimelineEventOverview{#e;constructor(e){super("responsiveness",null),this.#e=e}#n(){const{topLevelRendererIds:e}=this.#e.Meta,t=new Set(["LONG_TASK","FORCED_STYLE","IDLE_CALLBACK_OVER_TIME","FORCED_LAYOUT"]),i=new Set;for(const n of t){const t=this.#e.Warnings.perWarning.get(n);if(t)for(const n of t)e.has(n.pid)&&i.add(n)}return i}update(){super.update();const e=this.height(),{traceBounds:t}=this.#e.Meta,i=t.range,n=this.width()/i,r=this.context(),s=new Path2D,a=new Path2D,o=this.#n();for(const e of o)l(e);function l(i){const{startTime:r,duration:o}=TraceEngine.Helpers.Timing.eventTimingsMicroSeconds(i),l=Math.round(n*(r-t.min)),c=Math.round(n*o);s.rect(l,0,c,e),a.moveTo(l+c,0),a.lineTo(l+c,e)}r.fillStyle="hsl(0, 80%, 90%)",r.strokeStyle="red",r.lineWidth=2*window.devicePixelRatio,r.fill(s),r.stroke(a)}}export class TimelineFilmStripOverview extends TimelineEventOverview{frameToImagePromise;lastFrame=null;lastElement;drawGeneration;emptyImage;#r=null;constructor(e){super("filmstrip",null),this.frameToImagePromise=new Map,this.#r=e,this.lastFrame=null,this.lastElement=null,this.reset()}update(){super.update();const e=this.#r?this.#r.frames:[];if(!e.length)return;if(0===this.height())return void console.warn("TimelineFilmStrip could not be drawn as its canvas height is 0");const t=Symbol("drawGeneration");this.drawGeneration=t,this.imageByFrame(e[0]).then((e=>{if(this.drawGeneration!==t)return;if(!e||!e.naturalWidth||!e.naturalHeight)return;const i=this.height()-2*TimelineFilmStripOverview.Padding,n=Math.ceil(i*e.naturalWidth/e.naturalHeight),r=Math.min(200/e.naturalWidth,1);this.emptyImage=new Image(e.naturalWidth*r,e.naturalHeight*r),this.drawFrames(n,i)}))}async imageByFrame(e){let t=this.frameToImagePromise.get(e);if(!t){const i=e.screenshotAsString;t=UI.UIUtils.loadImageFromData(i),this.frameToImagePromise.set(e,t)}return t}drawFrames(e,t){if(!e)return;if(!this.#r||this.#r.frames.length<1)return;const i=TimelineFilmStripOverview.Padding,n=this.width(),r=TraceEngine.Helpers.Timing.microSecondsToMilliseconds(this.#r.zeroTime),s=TraceEngine.Helpers.Timing.microSecondsToMilliseconds(this.#r.spanTime)/n,a=this.context(),o=this.drawGeneration;a.beginPath();for(let o=i;o<n;o+=e+2*i){const i=TraceEngine.Types.Timing.MilliSeconds(r+(o+e/2)*s),n=TraceEngine.Helpers.Timing.millisecondsToMicroseconds(i),c=TraceEngine.Extras.FilmStrip.frameClosestToTimestamp(this.#r,n);c&&(a.rect(o-.5,.5,e+1,t+1),this.imageByFrame(c).then(l.bind(this,o)))}function l(i,n){this.drawGeneration===o&&n&&a.drawImage(n,i,1,e,t)}a.strokeStyle="#ddd",a.stroke()}async overviewInfoPromise(e){if(!this.#r||0===this.#r.frames.length)return null;const t=this.calculator();if(!t)return null;const i=TraceEngine.Types.Timing.MilliSeconds(t.positionToTime(e)),n=TraceEngine.Helpers.Timing.millisecondsToMicroseconds(i),r=TraceEngine.Extras.FilmStrip.frameClosestToTimestamp(this.#r,n);if(r===this.lastFrame)return this.lastElement;const s=r?this.imageByFrame(r):Promise.resolve(this.emptyImage),a=await s,o=document.createElement("div");return o.classList.add("frame"),a&&o.createChild("div","thumbnail").appendChild(a),this.lastFrame=r,this.lastElement=o,o}reset(){this.lastFrame=null,this.lastElement=null,this.frameToImagePromise=new Map}static Padding=2}export class TimelineEventOverviewMemory extends TimelineEventOverview{heapSizeLabel;#e;constructor(e){super("memory",i18nString(UIStrings.heap)),this.heapSizeLabel=this.element.createChild("div","memory-graph-label"),this.#e=e}resetHeapSizeLabels(){this.heapSizeLabel.textContent=""}update(){super.update();const e=window.devicePixelRatio;if(0===this.#e.Memory.updateCountersByProcess.size)return void this.resetHeapSizeLabels();const t=Array.from(this.#e.Meta.topLevelRendererIds).map((e=>this.#e.Memory.updateCountersByProcess.get(e)||[])).filter((e=>e.length>0)),i=3*e;let n=0,r=1e11;const s=TraceEngine.Helpers.Timing.traceBoundsMilliseconds(this.#e.Meta.traceBounds),a=s.min,o=s.max;function l(e){const t=e.args.data;t&&t.jsHeapSizeUsed&&(n=Math.max(n,t.jsHeapSizeUsed),r=Math.min(r,t.jsHeapSizeUsed))}for(let e=0;e<t.length;e++)t[e].forEach(l);r=Math.min(r,n);const c=this.width(),m=this.height()-i,h=c/(o-a),d=(m-1)/Math.max(n-r,1),u=new Array(c);function p(e){const t=e.args.data;if(!t||!t.jsHeapSizeUsed)return;const{startTime:i}=TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(e),n=Math.round((i-a)*h),s=Math.round((t.jsHeapSizeUsed-r)*d);u[n]=Math.max(u[n]||0,s)}for(let e=0;e<t.length;e++)t[e].forEach(p);const g=this.context(),T=m+i+1;g.translate(.5,.5),g.beginPath(),g.moveTo(-1,T);let f=0,v=!0,S=0;for(let e=0;e<u.length;e++){if(void 0===u[e])continue;v&&(v=!1,f=u[e],g.lineTo(-1,m-f));const t=u[e];Math.abs(t-f)>2&&Math.abs(e-S)>1&&g.lineTo(e,m-f),f=t,g.lineTo(e,m-f),S=e}g.lineTo(c+1,m-f),g.lineTo(c+1,T),g.closePath(),g.fillStyle="hsla(220, 90%, 70%, 0.2)",g.fill(),g.lineWidth=1,g.strokeStyle="hsl(220, 90%, 70%)",g.stroke(),this.heapSizeLabel.textContent=i18nString(UIStrings.sSDash,{PH1:Platform.NumberUtilities.bytesToString(r),PH2:Platform.NumberUtilities.bytesToString(n)})}}export class Quantizer{lastTime;quantDuration;callback;counters;remainder;constructor(e,t,i){this.lastTime=e,this.quantDuration=t,this.callback=i,this.counters=[],this.remainder=t}appendInterval(e,t){let i=e-this.lastTime;if(i<=this.remainder)return this.counters[t]=(this.counters[t]||0)+i,this.remainder-=i,void(this.lastTime=e);for(this.counters[t]=(this.counters[t]||0)+this.remainder,this.callback(this.counters),i-=this.remainder;i>=this.quantDuration;){const e=[];e[t]=this.quantDuration,this.callback(e),i-=this.quantDuration}this.counters=[],this.counters[t]=i,this.lastTime=e,this.remainder=this.quantDuration-i}}