UNPKG

chrome-devtools-frontend

Version:
137 lines (124 loc) 6.03 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 type * as Common from '../../core/common/common.js'; import * as i18n from '../../core/i18n/i18n.js'; import * as Trace from '../../models/trace/trace.js'; import type * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js'; import * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js'; import type {VisualLoggingTrackName} from './CompatibilityTracksAppender.js'; const UIStrings = { /** * @description Text in the Performance panel to show how long was spent in a particular part of the code. * The first placeholder is the total time taken for this node and all children, the second is the self time * (time taken in this node, without children included). *@example {10ms} PH1 *@example {10ms} PH2 */ sSelfS: '{PH1} (self {PH2})', } as const; const str_ = i18n.i18n.registerUIStrings('panels/timeline/AppenderUtils.ts', UIStrings); const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); /** An array, indexed by entry levels, where the values are the last timestamp (typically `endTime`) of data within that level. */ export type LastTimestampByLevel = number[]; /** * Builds the style for the group. * Each group has a predefined style and a reference to the definition of the legacy track (which should be removed in the future). * @param extra the customized fields with value. * @returns the built GroupStyle */ export function buildGroupStyle(extra?: Partial<PerfUI.FlameChart.GroupStyle>): PerfUI.FlameChart.GroupStyle { const defaultGroupStyle: PerfUI.FlameChart.GroupStyle = { padding: 4, height: 17, collapsible: true, color: ThemeSupport.ThemeSupport.instance().getComputedValue('--sys-color-on-surface'), backgroundColor: ThemeSupport.ThemeSupport.instance().getComputedValue('--sys-color-cdt-base-container'), nestingLevel: 0, shareHeaderLine: true, }; return Object.assign(defaultGroupStyle, extra); } /** * Builds the header corresponding to the track. A header is added in the shape of a group in the flame chart data. * @param jslogContext the text that will be set as the logging context * for the Visual Elements logging framework. Pass * `null` to not set a context and consequently * cause this group not to be logged. * @param startLevel the flame chart level at which the track header is appended. * @param name the display name of the track. * @param style the GroupStyle for the track header. * @param selectable if the track is selectable. * @param expanded if the track is expanded. * @param track this is set only when `selectable` is true, and it is used for selecting a track in the details panel. * @param showStackContextMenu whether menu with options to merge/collapse entries in track is shown. * @returns the group that built from the give data */ export function buildTrackHeader( jslogContext: VisualLoggingTrackName|null, startLevel: number, name: string, style: PerfUI.FlameChart.GroupStyle, selectable: boolean, expanded?: boolean, showStackContextMenu?: boolean): PerfUI.FlameChart.Group { const group: PerfUI.FlameChart.Group = { startLevel, name: name as Common.UIString.LocalizedString, style, selectable, expanded, showStackContextMenu, }; if (jslogContext !== null) { group.jslogContext = jslogContext; } return group; } /** * Returns the time info shown when an event is hovered in the timeline. * @param totalTime the total time of the hovered event. * @param selfTime the self time of the hovered event. * @returns the formatted time string for popoverInfo */ export function getDurationString(totalTime?: Trace.Types.Timing.Micro, selfTime?: Trace.Types.Timing.Micro): string { if (!totalTime) { return ''; } const totalMs = Trace.Helpers.Timing.microToMilli(totalTime); if (selfTime === undefined) { return i18n.TimeUtilities.millisToString(totalMs, true); } const selfMs = Trace.Helpers.Timing.microToMilli(selfTime); // This minSelfTimeSignificance is 0.001µs, aka 1 nanosecond. // TODO(paulirish): change to 0.09ms, aka 90 microseconds and revise logic below. const minSelfTimeSignificance = Trace.Types.Timing.Milli(0.000001); const formattedTime = Math.abs(totalMs - selfMs) > minSelfTimeSignificance && selfMs > minSelfTimeSignificance ? i18nString(UIStrings.sSelfS, { PH1: i18n.TimeUtilities.millisToString(totalMs, true), PH2: i18n.TimeUtilities.millisToString(selfMs, true), }) : i18n.TimeUtilities.millisToString(totalMs, true); return formattedTime; } /** * Returns the first level that is available for an event. * Important: if you are walking through an array of events and calling this, * the events MUST be sorted. */ export function getEventLevel(event: Trace.Types.Events.Event, lastTimestampByLevel: LastTimestampByLevel): number { let level = 0; const startTime = event.ts; const endTime = event.ts + (event.dur || 0); // Look vertically for the first level where this event fits, // that is, where it wouldn't overlap with other events. while (level < lastTimestampByLevel.length && startTime < lastTimestampByLevel[level]) { // For each event, we look each level from top, and see if start timestamp of this // event is used by current level already. If yes, we will go to check next level. ++level; } lastTimestampByLevel[level] = endTime; return level; } export function addDecorationToEvent( timelineData: PerfUI.FlameChart.FlameChartTimelineData, eventIndex: number, decoration: PerfUI.FlameChart.FlameChartDecoration): void { const decorationsForEvent = timelineData.entryDecorations[eventIndex] || []; decorationsForEvent.push(decoration); timelineData.entryDecorations[eventIndex] = decorationsForEvent; }