UNPKG

chrome-devtools-frontend

Version:
87 lines (78 loc) 3.37 kB
// Copyright 2023 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. import * as Helpers from '../helpers/helpers.js'; import * as Types from '../types/types.js'; const IDLE_FUNCTION_CALL_NAMES = new Set([ '(program)', '(idle)', '(root)', ]); export function calculateWindow( traceBounds: Types.Timing.TraceWindowMicro, mainThreadEntries: readonly Types.Events.Event[]): Types.Timing.TraceWindowMicro { if (!mainThreadEntries.length) { return traceBounds; } const entriesWithIdleRemoved = mainThreadEntries.filter(entry => { if (Types.Events.isProfileCall(entry) && (IDLE_FUNCTION_CALL_NAMES.has(entry.callFrame.functionName) || !entry.callFrame.functionName)) { return false; } return true; }); if (entriesWithIdleRemoved.length === 0) { return traceBounds; } /** * Calculates regions of low utilization and returns the index of the event * that is the first event that should be included. **/ function findLowUtilizationRegion(startIndex: number, stopIndex: number): number { const threshold = 0.1; let cutIndex = startIndex; const entryAtCut = entriesWithIdleRemoved[cutIndex]; const timings = Helpers.Timing.eventTimingsMicroSeconds(entryAtCut); let cutTime = (timings.startTime + timings.endTime) / 2; let usedTime = 0; const step = Math.sign(stopIndex - startIndex); for (let i = startIndex; i !== stopIndex; i += step) { const task = entriesWithIdleRemoved[i]; const taskTimings = Helpers.Timing.eventTimingsMicroSeconds(task); const taskTime = (taskTimings.startTime + taskTimings.endTime) / 2; const interval = Math.abs(cutTime - taskTime); if (usedTime < threshold * interval) { cutIndex = i; cutTime = taskTime; usedTime = 0; } usedTime += taskTimings.duration; } return cutIndex; } const rightIndex = findLowUtilizationRegion(entriesWithIdleRemoved.length - 1, 0); const leftIndex = findLowUtilizationRegion(0, rightIndex); const leftTimings = Helpers.Timing.eventTimingsMicroSeconds(entriesWithIdleRemoved[leftIndex]); const rightTimings = Helpers.Timing.eventTimingsMicroSeconds(entriesWithIdleRemoved[rightIndex]); let leftTime = leftTimings.startTime; let rightTime = rightTimings.endTime; const zoomedInSpan = rightTime - leftTime; if (zoomedInSpan < traceBounds.range * 0.1) { // If the area we have chosen to zoom into is less than 10% of the entire // span, we bail and show the entire trace. It would not be so useful to // the user to zoom in on such a small area; we assume they have // purposefully recorded a trace that contains empty periods of time. return traceBounds; } // Adjust the left time down by 5%, and the right time up by 5%, so that // we give the range we want to zoom a bit of breathing space. At the // same time, ensure that we do not stray beyond the bounds of the // min/max time of the entire trace. leftTime = Types.Timing.Micro(Math.max(leftTime - 0.05 * zoomedInSpan, traceBounds.min)); rightTime = Types.Timing.Micro(Math.min(rightTime + 0.05 * zoomedInSpan, traceBounds.max)); return { min: leftTime, max: rightTime, range: Types.Timing.Micro(rightTime - leftTime), }; }