mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Implement Performance.measure support for RN (JS side)
Summary: Changelog: [Internal] This adds JS side implementation (including the API) for the `Performance.measure` functionality, [as described in the corresponding standard](https://www.w3.org/TR/user-timing/#measure-method). The JS part is separated from the C++ implementation (further down the stack) to help the review being more focused. Reviewed By: mdvacca Differential Revision: D41733190 fbshipit-source-id: 72b69f6bb332aed4b9477a186b0e818b62009220
This commit is contained in:
committed by
Facebook GitHub Bot
parent
7a9ed166aa
commit
d8bcab2be7
@@ -22,4 +22,21 @@ void NativePerformance::mark(
|
||||
PerformanceEntryReporter::getInstance().mark(name, startTime, duration);
|
||||
}
|
||||
|
||||
void NativePerformance::clearMarks(
|
||||
jsi::Runtime &rt,
|
||||
std::optional<std::string> markName) {}
|
||||
|
||||
void NativePerformance::measure(
|
||||
jsi::Runtime &rt,
|
||||
std::string name,
|
||||
double startTime,
|
||||
double endTime,
|
||||
std::optional<double> duration,
|
||||
std::optional<std::string> startMark,
|
||||
std::optional<std::string> endMark) {}
|
||||
|
||||
void NativePerformance::clearMeasures(
|
||||
jsi::Runtime &rt,
|
||||
std::optional<std::string> measureName) {}
|
||||
|
||||
} // namespace facebook::react
|
||||
|
||||
@@ -27,6 +27,18 @@ class NativePerformance : public NativePerformanceCxxSpec<NativePerformance>,
|
||||
|
||||
void
|
||||
mark(jsi::Runtime &rt, std::string name, double startTime, double duration);
|
||||
void clearMarks(jsi::Runtime &rt, std::optional<std::string> markName);
|
||||
|
||||
void measure(
|
||||
jsi::Runtime &rt,
|
||||
std::string name,
|
||||
double startTime,
|
||||
double endTime,
|
||||
std::optional<double> duration,
|
||||
std::optional<std::string> startMark,
|
||||
std::optional<std::string> endMark);
|
||||
|
||||
void clearMeasures(jsi::Runtime &rt, std::optional<std::string> measureName);
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
@@ -14,6 +14,17 @@ import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry';
|
||||
|
||||
export interface Spec extends TurboModule {
|
||||
+mark?: (name: string, startTime: number, duration: number) => void;
|
||||
+clearMarks?: (markName?: string) => void;
|
||||
|
||||
+measure?: (
|
||||
name: string,
|
||||
startTime: number,
|
||||
endTime: number,
|
||||
duration?: number,
|
||||
startMark?: string,
|
||||
endMark?: string,
|
||||
) => void;
|
||||
+clearMeasures?: (measureName?: string) => void;
|
||||
}
|
||||
|
||||
export default (TurboModuleRegistry.get<Spec>('NativePerformanceCxx'): ?Spec);
|
||||
|
||||
@@ -15,6 +15,7 @@ import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry';
|
||||
export const RawPerformanceEntryTypeValues = {
|
||||
UNDEFINED: 0,
|
||||
MARK: 1,
|
||||
MEASURE: 2,
|
||||
};
|
||||
|
||||
export type RawPerformanceEntryType = number;
|
||||
|
||||
@@ -36,6 +36,30 @@ export class PerformanceMark extends PerformanceEntry {
|
||||
}
|
||||
}
|
||||
|
||||
export type TimeStampOrName = HighResTimeStamp | string;
|
||||
|
||||
export type PerformanceMeasureOptions = {
|
||||
detail?: DetailType,
|
||||
start?: TimeStampOrName,
|
||||
end?: TimeStampOrName,
|
||||
duration?: HighResTimeStamp,
|
||||
};
|
||||
|
||||
export class PerformanceMeasure extends PerformanceEntry {
|
||||
detail: DetailType;
|
||||
constructor(measureName: string, measureOptions?: PerformanceMeasureOptions) {
|
||||
super({
|
||||
name: measureName,
|
||||
entryType: 'measure',
|
||||
startTime: 0,
|
||||
duration: measureOptions?.duration ?? 0,
|
||||
});
|
||||
if (measureOptions !== undefined) {
|
||||
this.detail = measureOptions.detail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Partial implementation of the Performance interface for RN,
|
||||
* corresponding to the standard in
|
||||
@@ -50,8 +74,73 @@ export default class Performance {
|
||||
NativePerformance?.mark?.(markName, mark.startTime, mark.duration);
|
||||
return mark;
|
||||
}
|
||||
clearMarks(markName?: string): void {
|
||||
NativePerformance?.clearMarks?.(markName);
|
||||
}
|
||||
|
||||
clearMarks(markName?: string): void {}
|
||||
measure(
|
||||
measureName: string,
|
||||
startMarkOrOptions?: string | PerformanceMeasureOptions,
|
||||
endMark?: string,
|
||||
): PerformanceMeasure {
|
||||
let options;
|
||||
let startMarkName,
|
||||
endMarkName = endMark,
|
||||
duration,
|
||||
startTime = 0,
|
||||
endTime = 0;
|
||||
if (typeof startMarkOrOptions === 'string') {
|
||||
startMarkName = startMarkOrOptions;
|
||||
} else if (startMarkOrOptions !== undefined) {
|
||||
options = startMarkOrOptions;
|
||||
if (endMark !== undefined) {
|
||||
throw new TypeError(
|
||||
"Performance.measure: Can't have both options and endMark",
|
||||
);
|
||||
}
|
||||
if (options.start === undefined && options.end === undefined) {
|
||||
throw new TypeError(
|
||||
'Performance.measure: Must have at least one of start/end specified in options',
|
||||
);
|
||||
}
|
||||
if (
|
||||
options.start !== undefined &&
|
||||
options.end !== undefined &&
|
||||
options.duration !== undefined
|
||||
) {
|
||||
throw new TypeError(
|
||||
"Performance.measure: Can't have both start/end and duration explicitly in options",
|
||||
);
|
||||
}
|
||||
|
||||
if (typeof options.start === 'number') {
|
||||
startTime = options.start;
|
||||
} else {
|
||||
startMarkName = options.start;
|
||||
}
|
||||
|
||||
if (typeof options.end === 'number') {
|
||||
endTime = options.end;
|
||||
} else {
|
||||
endMarkName = options.end;
|
||||
}
|
||||
|
||||
duration = options.duration ?? duration;
|
||||
}
|
||||
const measure = new PerformanceMeasure(measureName, options);
|
||||
NativePerformance?.measure?.(
|
||||
measureName,
|
||||
startTime,
|
||||
endTime,
|
||||
duration,
|
||||
startMarkName,
|
||||
endMarkName,
|
||||
);
|
||||
return measure;
|
||||
}
|
||||
clearMeasures(measureName?: string): void {
|
||||
NativePerformance?.clearMeasures?.(measureName);
|
||||
}
|
||||
|
||||
now(): HighResTimeStamp {
|
||||
return getCurrentTimeStamp();
|
||||
|
||||
@@ -14,11 +14,12 @@ import type {
|
||||
} from './NativePerformanceObserver';
|
||||
|
||||
import warnOnce from '../Utilities/warnOnce';
|
||||
import NativePerformanceObserver from './NativePerformanceObserver';
|
||||
import NativePerformanceObserver, {
|
||||
RawPerformanceEntryTypeValues,
|
||||
} from './NativePerformanceObserver';
|
||||
|
||||
export type HighResTimeStamp = number;
|
||||
// TODO: Extend once new types (such as event) are supported.
|
||||
export type PerformanceEntryType = 'mark';
|
||||
export type PerformanceEntryType = 'mark' | 'measure';
|
||||
|
||||
export class PerformanceEntry {
|
||||
name: string;
|
||||
@@ -52,7 +53,11 @@ export class PerformanceEntry {
|
||||
function rawToPerformanceEntryType(
|
||||
type: RawPerformanceEntryType,
|
||||
): PerformanceEntryType {
|
||||
return 'mark';
|
||||
if (type === RawPerformanceEntryTypeValues.MARK) {
|
||||
return 'mark';
|
||||
} else {
|
||||
return 'measure';
|
||||
}
|
||||
}
|
||||
|
||||
function rawToPerformanceEntry(entry: RawPerformanceEntry): PerformanceEntry {
|
||||
@@ -232,5 +237,5 @@ export default class PerformanceObserver {
|
||||
|
||||
static supportedEntryTypes: $ReadOnlyArray<PerformanceEntryType> =
|
||||
// TODO: add types once they are fully supported
|
||||
Object.freeze(['mark']);
|
||||
Object.freeze(['mark', 'measure']);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user