Skip to content

Commit d883108

Browse files
hoxyqfacebook-github-bot
authored andcommitted
Define HighResTimeStamp, HighResTimeDuration, HighResTimeClock (facebook#51254)
Summary: Pull Request resolved: facebook#51254 # Changelog: [Internal] Defines single timestamp abstraction that will be used in C++ layer of React Native core: Key primitives include: - `HighResTimeStamp`: A class representing a specific point in time with high precision. - `HighResTimeDuration`: A class representing a duration of time with high precision. - `HighResTimeClock`: A class providing a monotonic clock that won't be adjusted. Right now, all these just encapsulate `std::chrono::steady_clock` with no extra custom logic. We might revisit this in a future, once we decide to add support for [`Performance.timeOrigin`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/timeOrigin). This diff also adds a `README.md` documentation file with a brief summary of the `react/timing` module. Differential Revision: D72796412
1 parent af9c2bb commit d883108

File tree

3 files changed

+528
-0
lines changed

3 files changed

+528
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# React Native Timing
2+
3+
[🏠 Home](../../../../../../__docs__/README.md)
4+
5+
This directory contains the shared C++ implementation of high-resolution timing
6+
primitives for React Native. These primitives provide precise time measurement
7+
capabilities that align with Web standards while being optimized for the React
8+
Native environment.
9+
10+
## 🚀 Usage
11+
12+
The timing primitives in this module are primarily used by internal React Native
13+
systems that require precise time measurements. They are not typically used
14+
directly by application developers but serve as foundational components for
15+
various React Native features.
16+
17+
Key primitives include:
18+
19+
- `HighResTimeStamp`: A class representing a specific point in time with high
20+
precision.
21+
- `HighResTimeDuration`: A class representing a duration of time with high
22+
precision.
23+
- `HighResTimeClock`: A class providing a monotonic clock that won't be
24+
adjusted.
25+
26+
These primitives support various operations:
27+
28+
```cpp
29+
// Getting the current high-resolution timestamp
30+
auto now = HighResTimeClock::now();
31+
32+
// Creating durations
33+
auto duration = HighResTimeDuration(std::chrono::milliseconds(100));
34+
35+
// Arithmetic operations
36+
auto later = now + duration;
37+
auto elapsed = later - now;
38+
39+
// Converting to different time units with high precision
40+
int64_t nanoseconds = now.toNanoseconds();
41+
int64_t microseconds = now.toMicroseconds();
42+
int64_t milliseconds = now.toMilliseconds();
43+
44+
// Converting to DOMHighResTimeStamp (for JavaScript interoperability)
45+
double jsTimeValue = now.toDOMHighResTimeStamp();
46+
```
47+
48+
## 📐 Design
49+
50+
The timing primitives are designed to align with Web standards while leveraging
51+
C++'s type system and the performance characteristics of native code. The
52+
implementation uses `std::chrono` internally but provides a more specialized
53+
interface tailored to React Native's needs.
54+
55+
### HighResTimeStamp
56+
57+
This class represents a specific point in time with high precision. It
58+
encapsulates a `std::chrono::steady_clock::time_point` and provides methods to:
59+
60+
- Convert to `DOMHighResTimeStamp` for JavaScript interoperability.
61+
- Perform arithmetic operations with durations.
62+
- Compare with other timestamps.
63+
64+
### HighResTimeDuration
65+
66+
This class represents a duration of time with high precision. It encapsulates a
67+
`std::chrono::duration` and provides methods to:
68+
69+
- Convert to `DOMHighResTimeStamp` for JavaScript interoperability.
70+
- Perform arithmetic operations.
71+
- Compare with other durations.
72+
73+
### HighResTimeClock
74+
75+
This class provides access to a monotonic clock that will never be adjusted.
76+
It's based on `std::chrono::steady_clock` and ensures consistent time
77+
measurements even if the system clock is adjusted.
78+
79+
## 🔗 Relationship with other systems
80+
81+
### Used by
82+
83+
- [Event Loop](../../renderer/runtimescheduler/__docs__/README.md): Uses timing
84+
primitives for measuring task execution times and scheduling.
85+
- Web Performance API: Timing primitives are used to implement performance
86+
measurement APIs like `PerformanceObserver` entries (e.g., `longtask` and
87+
`event`).
88+
- React Native DevTools: The timing primitives integrate with the React Native
89+
DevTools tracing infrastructure to report the timing of tasks and events.
90+
91+
### Related to
92+
93+
- Web timing APIs: The timing primitives are designed to be compatible with Web
94+
timing concepts, making it easier to implement Web-compatible APIs in React
95+
Native.

packages/react-native/ReactCommon/react/timing/primitives.h

+258
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,262 @@ inline DOMHighResTimeStamp chronoToDOMHighResTimeStamp(
3030
return chronoToDOMHighResTimeStamp(timePoint.time_since_epoch());
3131
}
3232

33+
class HighResTimeDuration;
34+
class HighResTimeStamp;
35+
36+
/*
37+
* A class representing a duration of time with high precision.
38+
*
39+
* @see __docs__/README.md for more information.
40+
*/
41+
class HighResTimeDuration {
42+
friend class HighResTimeStamp;
43+
friend HighResTimeDuration operator-(
44+
const HighResTimeStamp& lhs,
45+
const HighResTimeStamp& rhs);
46+
friend HighResTimeStamp operator+(
47+
const HighResTimeStamp& lhs,
48+
const HighResTimeDuration& rhs);
49+
friend HighResTimeStamp operator-(
50+
const HighResTimeStamp& lhs,
51+
const HighResTimeDuration& rhs);
52+
53+
public:
54+
HighResTimeDuration()
55+
: chronoDuration_(std::chrono::steady_clock::duration()) {}
56+
/* implicit */ HighResTimeDuration(std::chrono::nanoseconds nanoseconds)
57+
: chronoDuration_(nanoseconds) {}
58+
/* implicit */ HighResTimeDuration(std::chrono::microseconds microseconds)
59+
: chronoDuration_(microseconds) {}
60+
/* implicit */ HighResTimeDuration(std::chrono::milliseconds milliseconds)
61+
: chronoDuration_(milliseconds) {}
62+
/* implicit */ HighResTimeDuration(std::chrono::seconds seconds)
63+
: chronoDuration_(seconds) {}
64+
65+
int64_t toNanoseconds() const {
66+
return std::chrono::duration_cast<std::chrono::nanoseconds>(chronoDuration_)
67+
.count();
68+
}
69+
70+
int64_t toMicroseconds() const {
71+
return std::chrono::duration_cast<std::chrono::microseconds>(
72+
chronoDuration_)
73+
.count();
74+
}
75+
76+
double toMicrosecondsWithPrecision() const {
77+
return static_cast<std::chrono::duration<double, std::micro>>(
78+
chronoDuration_)
79+
.count();
80+
}
81+
82+
int64_t toMilliseconds() const {
83+
return std::chrono::duration_cast<std::chrono::milliseconds>(
84+
chronoDuration_)
85+
.count();
86+
}
87+
88+
double toMillisecondsWithPrecision() const {
89+
return static_cast<std::chrono::duration<double, std::milli>>(
90+
chronoDuration_)
91+
.count();
92+
}
93+
94+
int64_t toSeconds() const {
95+
return std::chrono::duration_cast<std::chrono::seconds>(chronoDuration_)
96+
.count();
97+
}
98+
99+
double toSecondsWithPrecision() const {
100+
return static_cast<std::chrono::duration<double>>(chronoDuration_).count();
101+
}
102+
103+
double toDOMHighResTimeStamp() const {
104+
return toMillisecondsWithPrecision();
105+
}
106+
107+
HighResTimeDuration operator+(const HighResTimeDuration& rhs) const {
108+
return {chronoDuration_ + rhs.chronoDuration_};
109+
}
110+
111+
HighResTimeDuration operator-(const HighResTimeDuration& rhs) const {
112+
return {chronoDuration_ - rhs.chronoDuration_};
113+
}
114+
115+
HighResTimeDuration& operator+=(const HighResTimeDuration& rhs) {
116+
chronoDuration_ += rhs.chronoDuration_;
117+
return *this;
118+
}
119+
120+
HighResTimeDuration& operator-=(const HighResTimeDuration& rhs) {
121+
chronoDuration_ -= rhs.chronoDuration_;
122+
return *this;
123+
}
124+
125+
bool operator==(const HighResTimeDuration& rhs) const {
126+
return chronoDuration_ == rhs.chronoDuration_;
127+
}
128+
129+
bool operator!=(const HighResTimeDuration& rhs) const {
130+
return chronoDuration_ != rhs.chronoDuration_;
131+
}
132+
133+
bool operator<(const HighResTimeDuration& rhs) const {
134+
return chronoDuration_ < rhs.chronoDuration_;
135+
}
136+
137+
bool operator<=(const HighResTimeDuration& rhs) const {
138+
return chronoDuration_ <= rhs.chronoDuration_;
139+
}
140+
141+
bool operator>(const HighResTimeDuration& rhs) const {
142+
return chronoDuration_ > rhs.chronoDuration_;
143+
}
144+
145+
bool operator>=(const HighResTimeDuration& rhs) const {
146+
return chronoDuration_ >= rhs.chronoDuration_;
147+
}
148+
149+
private:
150+
std::chrono::steady_clock::duration chronoDuration_;
151+
};
152+
153+
/*
154+
* A class representing a specific point in time with high precision.
155+
*
156+
* @see __docs__/README.md for more information.
157+
*/
158+
class HighResTimeStamp {
159+
friend class HighResTimeClock;
160+
friend HighResTimeDuration operator-(
161+
const HighResTimeStamp& lhs,
162+
const HighResTimeStamp& rhs);
163+
friend HighResTimeStamp operator+(
164+
const HighResTimeStamp& lhs,
165+
const HighResTimeDuration& rhs);
166+
friend HighResTimeStamp operator-(
167+
const HighResTimeStamp& lhs,
168+
const HighResTimeDuration& rhs);
169+
170+
public:
171+
HighResTimeStamp()
172+
: chronoTimeStamp_(std::chrono::steady_clock::time_point()) {}
173+
explicit HighResTimeStamp(HighResTimeDuration duration)
174+
: chronoTimeStamp_(duration.chronoDuration_) {}
175+
/* implicit */ HighResTimeStamp(std::chrono::nanoseconds nanoseconds)
176+
: chronoTimeStamp_(nanoseconds) {}
177+
/* implicit */ HighResTimeStamp(std::chrono::microseconds microseconds)
178+
: chronoTimeStamp_(microseconds) {}
179+
/* implicit */ HighResTimeStamp(std::chrono::milliseconds milliseconds)
180+
: chronoTimeStamp_(milliseconds) {}
181+
/* implicit */ HighResTimeStamp(std::chrono::seconds seconds)
182+
: chronoTimeStamp_(seconds) {}
183+
184+
HighResTimeDuration toDuration() const {
185+
return {chronoTimeStamp_.time_since_epoch()};
186+
}
187+
188+
int64_t toNanoseconds() const {
189+
return toDuration().toNanoseconds();
190+
}
191+
192+
int64_t toMicroseconds() const {
193+
return toDuration().toMicroseconds();
194+
}
195+
196+
double toMicrosecondsWithPrecision() const {
197+
return toDuration().toMicrosecondsWithPrecision();
198+
}
199+
200+
int64_t toMilliseconds() const {
201+
return toDuration().toMilliseconds();
202+
}
203+
204+
double toMillisecondsWithPrecision() const {
205+
return toDuration().toMillisecondsWithPrecision();
206+
}
207+
208+
int64_t toSeconds() const {
209+
return toDuration().toSeconds();
210+
}
211+
212+
double toSecondsWithPrecision() const {
213+
return toDuration().toSecondsWithPrecision();
214+
}
215+
216+
double toDOMHighResTimeStamp() const {
217+
return toDuration().toDOMHighResTimeStamp();
218+
}
219+
220+
bool operator==(const HighResTimeStamp& rhs) const {
221+
return chronoTimeStamp_ == rhs.chronoTimeStamp_;
222+
}
223+
224+
bool operator!=(const HighResTimeStamp& rhs) const {
225+
return chronoTimeStamp_ != rhs.chronoTimeStamp_;
226+
}
227+
228+
bool operator<(const HighResTimeStamp& rhs) const {
229+
return chronoTimeStamp_ < rhs.chronoTimeStamp_;
230+
}
231+
232+
bool operator<=(const HighResTimeStamp& rhs) const {
233+
return chronoTimeStamp_ <= rhs.chronoTimeStamp_;
234+
}
235+
236+
bool operator>(const HighResTimeStamp& rhs) const {
237+
return chronoTimeStamp_ > rhs.chronoTimeStamp_;
238+
}
239+
240+
bool operator>=(const HighResTimeStamp& rhs) const {
241+
return chronoTimeStamp_ >= rhs.chronoTimeStamp_;
242+
}
243+
244+
HighResTimeStamp& operator+=(const HighResTimeDuration& rhs) {
245+
chronoTimeStamp_ += rhs.chronoDuration_;
246+
return *this;
247+
}
248+
249+
HighResTimeStamp& operator-=(const HighResTimeDuration& rhs) {
250+
chronoTimeStamp_ -= rhs.chronoDuration_;
251+
return *this;
252+
}
253+
254+
private:
255+
explicit HighResTimeStamp(std::chrono::steady_clock::time_point timeStamp)
256+
: chronoTimeStamp_(timeStamp) {}
257+
258+
std::chrono::steady_clock::time_point chronoTimeStamp_;
259+
};
260+
261+
/*
262+
* A class providing a monotonic clock that won't be adjusted.
263+
*
264+
* @see __docs__/README.md for more information.
265+
*/
266+
class HighResTimeClock {
267+
public:
268+
static HighResTimeStamp now() noexcept {
269+
return HighResTimeStamp(std::chrono::steady_clock::now());
270+
}
271+
};
272+
273+
inline HighResTimeDuration operator-(
274+
const HighResTimeStamp& lhs,
275+
const HighResTimeStamp& rhs) {
276+
return {lhs.chronoTimeStamp_ - rhs.chronoTimeStamp_};
277+
}
278+
279+
inline HighResTimeStamp operator+(
280+
const HighResTimeStamp& lhs,
281+
const HighResTimeDuration& rhs) {
282+
return HighResTimeStamp(lhs.chronoTimeStamp_ + rhs.chronoDuration_);
283+
}
284+
285+
inline HighResTimeStamp operator-(
286+
const HighResTimeStamp& lhs,
287+
const HighResTimeDuration& rhs) {
288+
return HighResTimeStamp(lhs.chronoTimeStamp_ - rhs.chronoDuration_);
289+
}
290+
33291
} // namespace facebook::react

0 commit comments

Comments
 (0)