UNPKG

@dcloudio/uni-debugger

Version:

uni-app debugger

152 lines (141 loc) 5.14 kB
// Copyright 2016 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. /** * @unrestricted */ PerfUI.LineLevelProfile = class { constructor() { this._locationPool = new Bindings.LiveLocationPool(); this.reset(); } /** * @return {!PerfUI.LineLevelProfile} */ static instance() { if (!PerfUI.LineLevelProfile._instance) PerfUI.LineLevelProfile._instance = new PerfUI.LineLevelProfile(); return PerfUI.LineLevelProfile._instance; } /** * @param {!SDK.CPUProfileDataModel} profile */ appendCPUProfile(profile) { const nodesToGo = [profile.profileHead]; const sampleDuration = (profile.profileEndTime - profile.profileStartTime) / profile.totalHitCount; while (nodesToGo.length) { const nodes = nodesToGo.pop().children; for (let i = 0; i < nodes.length; ++i) { const node = nodes[i]; nodesToGo.push(node); if (!node.url || !node.positionTicks) continue; let fileInfo = this._files.get(node.url); if (!fileInfo) { fileInfo = new Map(); this._files.set(node.url, fileInfo); } for (let j = 0; j < node.positionTicks.length; ++j) { const lineInfo = node.positionTicks[j]; const line = lineInfo.line; const time = lineInfo.ticks * sampleDuration; fileInfo.set(line, (fileInfo.get(line) || 0) + time); } } } this._scheduleUpdate(); } reset() { /** @type {!Map<string, !Map<number, number>>} */ this._files = new Map(); this._scheduleUpdate(); } _scheduleUpdate() { if (this._updateTimer) return; this._updateTimer = setTimeout(() => { this._updateTimer = null; this._doUpdate(); }, 0); } _doUpdate() { // TODO(alph): use scriptId instead of urls for the target. this._locationPool.disposeAll(); Workspace.workspace.uiSourceCodes().forEach( uiSourceCode => uiSourceCode.removeDecorationsForType(PerfUI.LineLevelProfile.LineDecorator.type)); for (const fileInfo of this._files) { const url = /** @type {string} */ (fileInfo[0]); const uiSourceCode = Workspace.workspace.uiSourceCodeForURL(url); if (!uiSourceCode) continue; const target = Bindings.NetworkProject.targetForUISourceCode(uiSourceCode) || SDK.targetManager.mainTarget(); const debuggerModel = target ? target.model(SDK.DebuggerModel) : null; if (!debuggerModel) continue; for (const lineInfo of fileInfo[1]) { const line = lineInfo[0] - 1; const time = lineInfo[1]; const rawLocation = debuggerModel.createRawLocationByURL(url, line, 0); if (rawLocation) new PerfUI.LineLevelProfile.Presentation(rawLocation, time, this._locationPool); else if (uiSourceCode) uiSourceCode.addLineDecoration(line, PerfUI.LineLevelProfile.LineDecorator.type, time); } } } }; /** * @unrestricted */ PerfUI.LineLevelProfile.Presentation = class { /** * @param {!SDK.DebuggerModel.Location} rawLocation * @param {number} time * @param {!Bindings.LiveLocationPool} locationPool */ constructor(rawLocation, time, locationPool) { this._time = time; Bindings.debuggerWorkspaceBinding.createLiveLocation(rawLocation, this.updateLocation.bind(this), locationPool); } /** * @param {!Bindings.LiveLocation} liveLocation */ updateLocation(liveLocation) { if (this._uiLocation) this._uiLocation.uiSourceCode.removeDecorationsForType(PerfUI.LineLevelProfile.LineDecorator.type); this._uiLocation = liveLocation.uiLocation(); if (this._uiLocation) { this._uiLocation.uiSourceCode.addLineDecoration( this._uiLocation.lineNumber, PerfUI.LineLevelProfile.LineDecorator.type, this._time); } } }; /** * @implements {SourceFrame.LineDecorator} * @unrestricted */ PerfUI.LineLevelProfile.LineDecorator = class { /** * @override * @param {!Workspace.UISourceCode} uiSourceCode * @param {!TextEditor.CodeMirrorTextEditor} textEditor */ decorate(uiSourceCode, textEditor) { const gutterType = 'CodeMirror-gutter-performance'; const decorations = uiSourceCode.decorationsForType(PerfUI.LineLevelProfile.LineDecorator.type); textEditor.uninstallGutter(gutterType); if (!decorations || !decorations.size) return; textEditor.installGutter(gutterType, false); for (const decoration of decorations) { const time = /** @type {number} */ (decoration.data()); const text = Common.UIString('%.1f\xa0ms', time); const intensity = Number.constrain(Math.log10(1 + 2 * time) / 5, 0.02, 1); const element = createElementWithClass('div', 'text-editor-line-marker-performance'); element.textContent = text; element.style.backgroundColor = `hsla(44, 100%, 50%, ${intensity.toFixed(3)})`; textEditor.setGutterDecoration(decoration.range().startLine, gutterType, element); } } }; PerfUI.LineLevelProfile.LineDecorator.type = 'performance';