1
0
Fork 0
firefox/devtools/client/fronts/perf.js
Daniel Baumann 5e9a113729
Adding upstream version 140.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-25 09:37:52 +02:00

127 lines
4.3 KiB
JavaScript

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
/**
* @typedef {import("perf").BulkReceiving} BulkReceiving
*/
const {
FrontClassWithSpec,
registerFront,
} = require("resource://devtools/shared/protocol.js");
const { perfSpec } = require("resource://devtools/shared/specs/perf.js");
class PerfFront extends FrontClassWithSpec(perfSpec) {
constructor(client, targetFront, parentFront) {
super(client, targetFront, parentFront);
// Attribute name from which to retrieve the actorID out of the target actor's form
this.formAttributeName = "perfActor";
}
/* @backward-compat { version 140 }
* Version 140 introduced the bulk transfer of the profile date, as
* implemented by getProfileAndStopProfilerBulk below.
* This function uses a trait to decide between calling the old method and the
* new method.
* In the case of the old method, the shared libraries are computed from the
* profile data itself. But when using the new method, the profile data is a
* gzipped buffer, therefore an additional call to
* getPreviouslyRetrievedAdditionalInformation is made to retrieve this
* information from the server-side.
*
* When we'll want to remove the backwards compatible code, we'll remove the
* second part of this function, but we'll likely keep the first part for
* simplicity.
* */
async getProfileAndStopProfiler() {
// Note: this.conn.traits exists sometimes, but isn't guaranteed to exist always.
// this.conn.mainRoot.traits always exists though.
const { useBulkTransferForPerformanceProfile } = this.conn.mainRoot.traits;
if (useBulkTransferForPerformanceProfile) {
const handle = await this.startCaptureAndStopProfiler();
// Start both calls in parallel
const profilePromise = this.getPreviouslyCapturedProfileDataBulk(handle);
const additionalInformationPromise =
this.getPreviouslyRetrievedAdditionalInformation(handle);
// But make sure we wait until the end of both calls even in case of an error.
const [profileResult, additionalInformationResult] =
await Promise.allSettled([
profilePromise,
additionalInformationPromise,
]);
if (profileResult.status === "rejected") {
throw profileResult.reason;
}
if (additionalInformationResult.status === "rejected") {
throw additionalInformationResult.reason;
}
return {
profile: profileResult.value,
additionalInformation: additionalInformationResult.value,
};
}
/**
* Flatten all the sharedLibraries of the different processes in the profile
* into one list of libraries.
* @param {any} processProfile - The profile JSON object
* @returns {Library[]}
*/
function sharedLibrariesFromProfile(processProfile) {
return processProfile.libs.concat(
...processProfile.processes.map(sharedLibrariesFromProfile)
);
}
const profileAsJson = await super.getProfileAndStopProfiler();
return {
profile: profileAsJson,
additionalInformation: {
sharedLibraries: sharedLibrariesFromProfile(profileAsJson),
},
};
}
/**
* This implements the retrieval of the profile data using the bulk protocol.
* @param {number} handle THe handle returned by startCaptureAndStopProfiler
*/
async getPreviouslyCapturedProfileDataBulk(handle) {
/**
* @typedef {BulkReceiving}
*/
const profileResult = await super.getPreviouslyCapturedProfileDataBulk(
handle
);
if (!profileResult) {
throw new Error(
"this.conn.request returns null or undefined, this is unexpected."
);
}
if (!profileResult.length) {
throw new Error(
"The profile result is an empty buffer, this is unexpected."
);
}
// We need to copy the data out of the stream we get using the bulk API.
// Note that the profile data is gzipped, but the profiler's frontend code
// knows how to deal with it.
const buffer = new ArrayBuffer(profileResult.length);
await profileResult.copyToBuffer(buffer);
return buffer;
}
}
registerFront(PerfFront);