@yuebai008/cli
Version:
Command line interface for rapid qg-minigame development
1 lines • 4.41 kB
JavaScript
import*as Root from"../../../core/root/root.js";import*as Common from"../../../core/common/common.js";import*as Types from"../types/types.js";import{millisecondsToMicroseconds}from"./Timing.js";import{mergeEventsInOrder}from"./Trace.js";export class SamplesIntegrator{#t=[];#e=[];#r;#s;#n=[];#i=!1;#o;#a=new Map;constructor(t,e,r){this.#o=t,this.#s=r,this.#r=e}buildProfileCalls(t){const e=mergeEventsInOrder(t,this.callsFromProfileSamples()),r=[];for(let t=0;t<e.length;t++){const s=e[t];if(0===r.length){if(Types.TraceEvents.isProfileCall(s)){this.#c(s);continue}r.push(s),this.#l(s);continue}const n=r.at(-1);if(void 0===n)continue;s.ts>=n.ts+(n.dur||0)?(this.#h(n),r.pop(),t--):Types.TraceEvents.isProfileCall(s)?this.#c(s,n):(this.#l(s),r.push(s))}for(;r.length;){const t=r.pop();t&&this.#h(t)}return this.#t}#l(t){"I"!==t.ph&&("RunMicrotasks"!==t.name&&"RunTask"!==t.name||(this.#n=[],this.#d(0,t.ts),this.#i=!1),this.#i&&(this.#d(this.#n.pop()||0,t.ts),this.#i=!1),this.#S(t),this.#n.push(this.#e.length))}#c(t,e){if(e&&SamplesIntegrator.isJSInvocationEvent(e)||this.#i)this.#S(t);else if(Types.TraceEvents.isProfileCall(t)&&0===this.#e.length){this.#i=!0;const e=this.#e.length;this.#S(t),this.#n.push(e)}}#h(t){const e=Types.Timing.MicroSeconds(t.ts+(t.dur||0));this.#d(this.#n.pop()||0,e)}callsFromProfileSamples(){const t=this.#o.samples,e=this.#o.timestamps;if(!t)return[];const r=[];let s;for(let n=0;n<t.length;n++){const t=this.#o.nodeByIndex(n),i=millisecondsToMicroseconds(Types.Timing.MilliSeconds(e[n]));if(!t)continue;const o=SamplesIntegrator.makeProfileCall(t,i,this.#r,this.#s);r.push(o),t.id===this.#o.gcNode?.id&&s?this.#a.set(o,s):s=t}return r}#m(t){let e=this.#o.nodeById(t.nodeId);const r=Boolean(e?.id===this.#o.gcNode?.id);if(r&&(e=this.#a.get(t)||null),!e)return[];const s=new Array(e.depth+1+Number(r));let n=s.length-1;for(r&&(s[n--]=t);e;)s[n--]=SamplesIntegrator.makeProfileCall(e,t.ts,this.#r,this.#s),e=e.parent;return s}#S(t){const e=Types.TraceEvents.isProfileCall(t)?this.#m(t):this.#e;SamplesIntegrator.filterStackFrames(e);const r=t.ts+(t.dur||0),s=Math.min(e.length,this.#e.length);let n;for(n=this.#n.at(-1)||0;n<s;++n){const t=e[n].callFrame,s=this.#e[n].callFrame;if(!SamplesIntegrator.framesAreEqual(t,s))break;this.#e[n].dur=Types.Timing.MicroSeconds(Math.max(this.#e[n].dur||0,r-this.#e[n].ts))}for(this.#d(n,t.ts);n<e.length;++n){const t=e[n];this.#e.push(t),t.nodeId!==this.#o.programNode?.id&&t.nodeId!==this.#o.root?.id&&t.nodeId!==this.#o.idleNode?.id&&this.#t.push(t)}}#d(t,e){if(this.#n.length){const r=this.#n.at(-1);r&&t<r&&(console.error(`Child stack is shallower (${t}) than the parent stack (${r}) at ${e}`),t=r)}this.#e.length<t&&(console.error(`Trying to truncate higher than the current stack size at ${e}`),t=this.#e.length);for(let t=0;t<this.#e.length;++t)this.#e[t].dur=Types.Timing.MicroSeconds(Math.max(e-this.#e[t].ts,0));this.#e.length=t}static isJSInvocationEvent(t){switch(t.name){case"RunMicrotasks":case"FunctionCall":case"EvaluateScript":case"v8.evaluateModule":case"EventDispatch":case"V8.Execute":return!0}return!(!t.name.startsWith("v8")&&!t.name.startsWith("V8"))}static framesAreEqual(t,e){return t.scriptId===e.scriptId&&t.functionName===e.functionName&&t.lineNumber===e.lineNumber}static showNativeName(t){try{return Root.Runtime.experiments.isEnabled("timelineV8RuntimeCallStats")&&Boolean(SamplesIntegrator.nativeGroup(t))}catch(t){return!1}}static nativeGroup(t){return t.startsWith("Parse")?"Parse":t.startsWith("Compile")||t.startsWith("Recompile")?"Compile":null}static isNativeRuntimeFrame(t){return"native V8Runtime"===t.url}static filterStackFrames(t){let e=!1;try{e=Root.Runtime.experiments.isEnabled("timelineShowAllEvents")}catch(t){}const r=Common.Settings.Settings.hasInstance()&&Common.Settings.Settings.instance().moduleSetting("showNativeFunctionsInJSProfile").get();if(e)return;let s=null,n=0;for(let e=0;e<t.length;++e){const i=t[e].callFrame,o=i.url,a=o&&o.startsWith("native ");if(!r&&a)continue;const c=SamplesIntegrator.isNativeRuntimeFrame(i);if(c&&!SamplesIntegrator.showNativeName(i.functionName))continue;const l=c?SamplesIntegrator.nativeGroup(i.functionName):null;s&&s===l||(s=l,t[n++]=t[e])}t.length=n}static makeProfileCall(t,e,r,s){return{cat:"",name:"ProfileCall",nodeId:t.id,ph:"X",pid:r,tid:s,ts:e,dur:Types.Timing.MicroSeconds(0),selfTime:Types.Timing.MicroSeconds(0),callFrame:t.callFrame}}}