UNPKG

@best/runner-headless

Version:

Best Runner (Headless)

121 lines 4.68 kB
"use strict"; /* * Copyright (c) 2019, salesforce.com, inc. * All rights reserved. * SPDX-License-Identifier: MIT * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.removeTrace = exports.mergeTracedMetrics = exports.parseTrace = void 0; const fs_1 = __importDefault(require("fs")); const util_1 = require("util"); const types_1 = require("@best/types"); const asyncReadFile = (0, util_1.promisify)(fs_1.default.readFile); const asyncUnlink = (0, util_1.promisify)(fs_1.default.unlink); const asyncExists = (0, util_1.promisify)(fs_1.default.exists); const TRACED_METRIC_EVENTS = ['Paint', 'Layout', 'UpdateLayoutTree', 'UpdateLayerTree', 'CompositeLayers']; const TRACED_EVENT_NAME_ALIAS = { UpdateLayoutTree: 'RecalculateStyles' }; const isBeginPhase = (event) => { return event.ph.toLowerCase() === 'b'; }; const isEndPhase = (event) => { return event.ph.toLowerCase() === 'e'; }; const hasDurationPhased = (event) => { return isBeginPhase(event) || isEndPhase(event); }; const sumPairedMetrics = (events) => { let duration = 0; for (const event of events) { if (isBeginPhase(event)) { duration -= event.ts; } else if (isEndPhase(event)) { duration += event.ts; } } return duration; }; // returns the total duration of all paints or layouts, etc in microseconds const sumEventDurations = (events) => { const pairedMetrics = events.filter(hasDurationPhased); if (pairedMetrics.length > 0 && pairedMetrics.length % 2 === 0) { return sumPairedMetrics(events); } return events.reduce((previous, current) => (previous += current.dur), 0); }; const parseTrace = async (tracePath) => { const file = await asyncReadFile(tracePath, 'utf8'); const trace = JSON.parse(file); const tracedMetricEvents = trace.traceEvents.filter((event) => TRACED_METRIC_EVENTS.includes(event.name) || event.name.includes(`${types_1.BenchmarkMeasureType.Execute}/`)); const sortedEvents = tracedMetricEvents.sort((a, b) => a.ts - b.ts); const groupedEvents = {}; let currentRun = false; for (const event of sortedEvents) { if (currentRun && TRACED_METRIC_EVENTS.includes(event.name)) { if (groupedEvents[currentRun][event.name]) { groupedEvents[currentRun][event.name].push(event); } else { groupedEvents[currentRun][event.name] = [event]; } } else if (event.name.includes(`${types_1.BenchmarkMeasureType.Execute}/`)) { if (isBeginPhase(event)) { currentRun = event.name; groupedEvents[event.name] = {}; } else if (isEndPhase(event)) { currentRun = false; } } } const tracedMetrics = Object.keys(groupedEvents).reduce((allMetrics, key) => { const runName = key.replace(`${types_1.BenchmarkMeasureType.Execute}/`, ''); const metrics = Object.keys(groupedEvents[key]).reduce((acc, eventName) => { const aliasEventName = TRACED_EVENT_NAME_ALIAS[eventName] || eventName; const name = aliasEventName.toLowerCase(); return { ...acc, [name]: sumEventDurations(groupedEvents[key][eventName]) / 1000, }; }, {}); return { ...allMetrics, [runName]: metrics, }; }, {}); return tracedMetrics; }; exports.parseTrace = parseTrace; const mergeTracedMetricsIntoResultNode = (resultNode, parsedTrace) => { if (resultNode.type === 'group') { resultNode.nodes.forEach((node) => { mergeTracedMetricsIntoResultNode(node, parsedTrace); }); } else if (resultNode.type === 'benchmark') { const nodeTraces = parsedTrace[resultNode.name]; resultNode.metrics = { ...resultNode.metrics, ...nodeTraces, }; } }; const mergeTracedMetrics = (benchmarkResults, parsedTrace) => { benchmarkResults.results.forEach((node) => { mergeTracedMetricsIntoResultNode(node, parsedTrace); }); }; exports.mergeTracedMetrics = mergeTracedMetrics; const removeTrace = async (tracePath) => { const fileExists = await asyncExists(tracePath); if (fileExists) { await asyncUnlink(tracePath); } }; exports.removeTrace = removeTrace; //# sourceMappingURL=trace.js.map