@yuebai008/cli
Version:
Command line interface for rapid qg-minigame development
1 lines • 5.62 kB
JavaScript
import*as Platform from"../../../core/platform/platform.js";import*as Helpers from"../helpers/helpers.js";import{data as metaHandlerData}from"./MetaHandler.js";import{data as samplesHandlerData}from"./SamplesHandler.js";import{KNOWN_EVENTS}from"./types.js";import*as Types from"../types/types.js";const processes=new Map,compositorTileWorkers=Array(),entryToNode=new Map,allRendererEvents=[];let nodeIdCount=0;const makeRendererEntrytNodeId=()=>++nodeIdCount,completeEventStack=[];let handlerState=1;const makeRendererProcess=()=>({url:null,isOnMainFrame:!1,threads:new Map}),makeRendererThread=()=>({name:null,entries:[]}),makeEmptyRendererTree=()=>({nodes:new Map,roots:new Set,maxDepth:0}),makeEmptyRendererEventNode=(e,r)=>({entry:e,id:r,parentId:null,childrenIds:new Set,depth:0}),getOrCreateRendererProcess=(e,r)=>Platform.MapUtilities.getWithDefault(e,r,makeRendererProcess),getOrCreateRendererThread=(e,r)=>Platform.MapUtilities.getWithDefault(e.threads,r,makeRendererThread);export function reset(){processes.clear(),entryToNode.clear(),allRendererEvents.length=0,completeEventStack.length=0,compositorTileWorkers.length=0,nodeIdCount=-1,handlerState=1}export function initialize(){if(1!==handlerState)throw new Error("Renderer Handler was not reset");handlerState=2}export function handleEvent(e){if(2!==handlerState)throw new Error("Renderer Handler is not initialized");if(Types.TraceEvents.isThreadName(e)&&e.args.name?.startsWith("CompositorTileWorker")&&compositorTileWorkers.push({pid:e.pid,tid:e.tid}),Types.TraceEvents.isTraceEventBegin(e)||Types.TraceEvents.isTraceEventEnd(e)){const r=getOrCreateRendererProcess(processes,e.pid),t=getOrCreateRendererThread(r,e.tid),n=makeCompleteEvent(e);if(!n)return;return t.entries.push(n),void allRendererEvents.push(n)}if(Types.TraceEvents.isTraceEventInstant(e)||Types.TraceEvents.isTraceEventComplete(e)){const r=getOrCreateRendererProcess(processes,e.pid);getOrCreateRendererThread(r,e.tid).entries.push(e),allRendererEvents.push(e)}}export async function finalize(){if(2!==handlerState)throw new Error("Renderer Handler is not initialized");const{mainFrameId:e,rendererProcessesByFrame:r,threadsInProcess:t}=metaHandlerData();assignMeta(processes,e,r,t),sanitizeProcesses(processes),buildHierarchy(processes,{filter:KNOWN_EVENTS}),sanitizeThreads(processes),handlerState=3}export function data(){if(3!==handlerState)throw new Error("Renderer Handler is not finalized");return{processes:new Map(processes),compositorTileWorkers:new Map(gatherCompositorThreads()),entryToNode:new Map(entryToNode),allRendererEvents:[...allRendererEvents]}}function gatherCompositorThreads(){const e=new Map;for(const r of compositorTileWorkers){const t=e.get(r.pid)||[];t.push(r.tid),e.set(r.pid,t)}return e}export function assignMeta(e,r,t,n){assignOrigin(e,t),assignIsMainFrame(e,r,t),assignThreadName(e,t,n)}export function assignOrigin(e,r){for(const t of r.values())for(const[r,n]of t)for(const t of n.flat()){const n=getOrCreateRendererProcess(e,r);if(null===n.url||"about:blank"===n.url)try{new URL(t.frame.url),n.url=t.frame.url}catch(e){n.url=null}}}export function assignIsMainFrame(e,r,t){for(const[n,s]of t)for(const[t]of s){const s=getOrCreateRendererProcess(e,t);n===r&&(s.isOnMainFrame=!0)}}export function assignThreadName(e,r,t){for(const[,n]of r)for(const[r]of n){const n=getOrCreateRendererProcess(e,r);for(const[e,s]of t.get(r)??[]){getOrCreateRendererThread(n,e).name=s?.args.name??`${e}`}}}export function sanitizeProcesses(e){for(const[r,t]of e){if(null===t.url){e.delete(r);continue}"about:"===new URL(t.url).protocol&&e.delete(r)}}export function sanitizeThreads(e){for(const[,r]of e)for(const[e,t]of r.threads)t.tree?.roots.size||r.threads.delete(e)}export function buildHierarchy(e,r){for(const[t,n]of e)for(const[e,s]of n.threads){if(!s.entries.length){s.tree=makeEmptyRendererTree();continue}Helpers.Trace.sortTraceEventsInPlace(s.entries);const n=samplesHandlerData().profilesInProcess.get(t)?.get(e)?.parsedProfile,o=n&&new Helpers.SamplesIntegrator.SamplesIntegrator(n,t,e),a=o?.buildProfileCalls(s.entries);a&&(s.entries=Helpers.Trace.mergeEventsInOrder(s.entries,a)),s.tree=treify(s.entries,r)}}export function treify(e,r){const t=[];nodeIdCount=-1;const n=makeEmptyRendererTree();for(let s=0;s<e.length;s++){const o=e[s];if(!r.filter.has(o.name))continue;const a=o.dur||0,i=makeRendererEntrytNodeId(),d=makeEmptyRendererEventNode(o,i);if(0===t.length){n.nodes.set(i,d),n.roots.add(i),o.selfTime=Types.Timing.MicroSeconds(a),t.push(d),n.maxDepth=Math.max(n.maxDepth,t.length),entryToNode.set(o,d);continue}const l=t.at(-1);if(void 0===l)throw new Error("Impossible: no parent node found in the stack");const c=l.entry,p=o.ts,m=c.ts,f=p+a,h=m+(c.dur||0);if(p<m)throw new Error("Impossible: current event starts before the parent event");if(p>=h){t.pop(),s--,nodeIdCount--;continue}f>h||(n.nodes.set(i,d),d.depth=t.length,d.parentId=l.id,l.childrenIds.add(i),o.selfTime=Types.Timing.MicroSeconds(a),void 0!==c.selfTime&&(c.selfTime=Types.Timing.MicroSeconds(c.selfTime-(o.dur||0))),t.push(d),n.maxDepth=Math.max(n.maxDepth,t.length),entryToNode.set(o,d))}return n}export function makeCompleteEvent(e){if(Types.TraceEvents.isTraceEventEnd(e)){const r=completeEventStack.pop();return r?r.name!==e.name||r.cat!==e.cat?(console.error("Begin/End events mismatch at "+r.ts+" ("+r.name+") vs. "+e.ts+" ("+e.name+")"),null):(r.dur=Types.Timing.MicroSeconds(e.ts-r.ts),null):null}const r={...e,ph:"X",dur:Types.Timing.MicroSeconds(0)};return completeEventStack.push(r),r}export function deps(){return["Meta","Samples"]}class RendererEventNodeIdTag{#e}