mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Implement performance.timeOrigin (#53660)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/53660 Changelog: [internal] (This is internal because these APIs aren't enabled in OSS yet) Implements `performance.timeOrigin` to allow converting timestamps from `performance.now()` to be based on the Unix epoch. This implementation isn't fully spec-compliant to align with the current implementation of `performance.now()`, where the base of the clock is system boot time instead of app startup / navigation time. Reviewed By: huntie Differential Revision: D82016724 fbshipit-source-id: e3a066721cecf41e2fd963beb94a0a2f1c5d6493
This commit is contained in:
committed by
Facebook GitHub Bot
parent
481fb612a2
commit
529f55c8c9
+9
@@ -131,9 +131,18 @@ NativePerformance::NativePerformance(std::shared_ptr<CallInvoker> jsInvoker)
|
||||
: NativePerformanceCxxSpec(std::move(jsInvoker)) {}
|
||||
|
||||
HighResTimeStamp NativePerformance::now(jsi::Runtime& /*rt*/) {
|
||||
// This is not spec-compliant, as this is the duration from system boot to
|
||||
// now, instead of from app startup to now.
|
||||
// This should be carefully changed eventually.
|
||||
return HighResTimeStamp::now();
|
||||
}
|
||||
|
||||
HighResDuration NativePerformance::timeOrigin(jsi::Runtime& /*rt*/) {
|
||||
// This is not spec-compliant, as this is an approximation from Unix epoch to
|
||||
// system boot, instead of a precise duration from Unix epoch to app startup.
|
||||
return HighResTimeStamp::unsafeOriginFromUnixTimeStamp();
|
||||
}
|
||||
|
||||
void NativePerformance::reportMark(
|
||||
jsi::Runtime& rt,
|
||||
const std::string& name,
|
||||
|
||||
+3
@@ -88,6 +88,9 @@ class NativePerformance : public NativePerformanceCxxSpec<NativePerformance> {
|
||||
// https://www.w3.org/TR/hr-time-3/#now-method
|
||||
HighResTimeStamp now(jsi::Runtime& rt);
|
||||
|
||||
// https://www.w3.org/TR/hr-time-3/#timeorigin-attribute
|
||||
HighResDuration timeOrigin(jsi::Runtime& rt);
|
||||
|
||||
#pragma mark - User Timing Level 3 functions (https://w3c.github.io/user-timing/)
|
||||
|
||||
void reportMark(
|
||||
|
||||
@@ -201,6 +201,11 @@ class HighResTimeStamp {
|
||||
return HighResTimeStamp(chronoNow());
|
||||
}
|
||||
|
||||
static HighResDuration unsafeOriginFromUnixTimeStamp() noexcept {
|
||||
static auto origin = computeUnsafeOriginFromUnixTimeStamp();
|
||||
return origin;
|
||||
}
|
||||
|
||||
static constexpr HighResTimeStamp min() noexcept {
|
||||
return HighResTimeStamp(std::chrono::steady_clock::time_point::min());
|
||||
}
|
||||
@@ -285,6 +290,13 @@ class HighResTimeStamp {
|
||||
|
||||
std::chrono::steady_clock::time_point chronoTimePoint_;
|
||||
|
||||
static HighResDuration computeUnsafeOriginFromUnixTimeStamp() noexcept {
|
||||
auto systemNow = std::chrono::system_clock::now();
|
||||
auto steadyNow = std::chrono::steady_clock::now();
|
||||
return HighResDuration(
|
||||
systemNow.time_since_epoch() - steadyNow.time_since_epoch());
|
||||
}
|
||||
|
||||
#ifdef REACT_NATIVE_DEBUG
|
||||
static std::function<std::chrono::steady_clock::time_point()>&
|
||||
getTimeStampProvider() {
|
||||
|
||||
@@ -199,11 +199,11 @@ declare interface EventCounts {
|
||||
}
|
||||
|
||||
declare class Performance {
|
||||
+eventCounts: EventCounts;
|
||||
+timeOrigin: DOMHighResTimeStamp;
|
||||
|
||||
clearMarks(name?: string): void;
|
||||
|
||||
clearMeasures(name?: string): void;
|
||||
|
||||
eventCounts: EventCounts;
|
||||
getEntries: (
|
||||
options?: PerformanceEntryFilterOptions,
|
||||
) => Array<PerformanceEntry>;
|
||||
@@ -215,7 +215,7 @@ declare class Performance {
|
||||
startMarkOrOptions?: string | PerformanceMeasureOptions,
|
||||
endMark?: string,
|
||||
): PerformanceMeasure;
|
||||
now: () => DOMHighResTimeStamp;
|
||||
now(): DOMHighResTimeStamp;
|
||||
toJSON(): string;
|
||||
}
|
||||
|
||||
|
||||
@@ -63,6 +63,7 @@ const cachedReportMeasure = NativePerformance.reportMeasure;
|
||||
const cachedGetMarkTime = NativePerformance.getMarkTime;
|
||||
const cachedNativeClearMarks = NativePerformance.clearMarks;
|
||||
const cachedNativeClearMeasures = NativePerformance.clearMeasures;
|
||||
let cachedTimeOrigin: ?DOMHighResTimeStamp;
|
||||
|
||||
const MARK_OPTIONS_REUSABLE_OBJECT: PerformanceMarkOptions = {
|
||||
startTime: 0,
|
||||
@@ -139,6 +140,24 @@ export default class Performance {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the high resolution timestamp that is used as the baseline for
|
||||
* performance-related timestamps.
|
||||
* https://developer.mozilla.org/en-US/docs/Web/API/Performance/timeOrigin
|
||||
*/
|
||||
get timeOrigin(): DOMHighResTimeStamp {
|
||||
if (cachedTimeOrigin == null) {
|
||||
if (NativePerformance.timeOrigin) {
|
||||
cachedTimeOrigin = NativePerformance?.timeOrigin();
|
||||
} else {
|
||||
// Very naive polyfill.
|
||||
cachedTimeOrigin = Date.now() - getCurrentTimeStamp();
|
||||
}
|
||||
}
|
||||
|
||||
return cachedTimeOrigin;
|
||||
}
|
||||
|
||||
mark(
|
||||
markName: string,
|
||||
markOptions?: PerformanceMarkOptions,
|
||||
|
||||
+33
@@ -22,4 +22,37 @@ describe('Performance', () => {
|
||||
return new PerformanceEntry();
|
||||
}).toThrow("Failed to construct 'PerformanceEntry': Illegal constructor");
|
||||
});
|
||||
|
||||
describe('now', () => {
|
||||
it('provides increasing timestamps since boot time', () => {
|
||||
const first = performance.now();
|
||||
const second = performance.now();
|
||||
const third = performance.now();
|
||||
|
||||
expect(typeof first).toBe('number');
|
||||
expect(typeof second).toBe('number');
|
||||
expect(typeof third).toBe('number');
|
||||
|
||||
expect(first).toBeGreaterThan(0);
|
||||
expect(second).toBeGreaterThan(first);
|
||||
expect(third).toBeGreaterThan(second);
|
||||
});
|
||||
});
|
||||
|
||||
describe('timeOrigin', () => {
|
||||
it('allows moving timestamps to Unix epoch', () => {
|
||||
// We need to truncate timestamps because `Date.now()` only provides
|
||||
// integer millisecond precision.
|
||||
const adjustedMonotonicTime = Math.trunc(
|
||||
performance.now() + performance.timeOrigin,
|
||||
);
|
||||
const wallTime = Date.now();
|
||||
const adjustedMonotonicTimeAfter = Math.trunc(
|
||||
performance.now() + performance.timeOrigin,
|
||||
);
|
||||
|
||||
expect(wallTime).toBeGreaterThanOrEqual(adjustedMonotonicTime);
|
||||
expect(adjustedMonotonicTimeAfter).toBeGreaterThanOrEqual(wallTime);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+2
@@ -54,6 +54,8 @@ export type PerformanceObserverInit = {
|
||||
|
||||
export interface Spec extends TurboModule {
|
||||
+now: () => number;
|
||||
+timeOrigin?: () => number;
|
||||
|
||||
+reportMark: (name: string, startTime: number, entry: mixed) => void;
|
||||
+reportMeasure: (
|
||||
name: string,
|
||||
|
||||
Reference in New Issue
Block a user