Skip to content

Commit 8e2e51e

Browse files
hoxyqfacebook-github-bot
authored andcommitted
Define HighResTimeStamp, HighResTimeDuration, HighResTimeClock
Summary: # 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 4cf7763 commit 8e2e51e

File tree

3 files changed

+440
-0
lines changed

3 files changed

+440
-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

+223
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,227 @@ 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+
int64_t toMilliseconds() const {
77+
return std::chrono::duration_cast<std::chrono::milliseconds>(
78+
chronoDuration_)
79+
.count();
80+
}
81+
82+
double toDOMHighResTimeStamp() const {
83+
return static_cast<std::chrono::duration<double, std::milli>>(
84+
chronoDuration_)
85+
.count();
86+
}
87+
88+
HighResTimeDuration operator+(const HighResTimeDuration& rhs) const {
89+
return {chronoDuration_ + rhs.chronoDuration_};
90+
}
91+
92+
HighResTimeDuration operator-(const HighResTimeDuration& rhs) const {
93+
return {chronoDuration_ - rhs.chronoDuration_};
94+
}
95+
96+
HighResTimeDuration& operator+=(const HighResTimeDuration& rhs) {
97+
chronoDuration_ += rhs.chronoDuration_;
98+
return *this;
99+
}
100+
101+
HighResTimeDuration& operator-=(const HighResTimeDuration& rhs) {
102+
chronoDuration_ -= rhs.chronoDuration_;
103+
return *this;
104+
}
105+
106+
bool operator==(const HighResTimeDuration& rhs) const {
107+
return chronoDuration_ == rhs.chronoDuration_;
108+
}
109+
110+
bool operator!=(const HighResTimeDuration& rhs) const {
111+
return chronoDuration_ != rhs.chronoDuration_;
112+
}
113+
114+
bool operator<(const HighResTimeDuration& rhs) const {
115+
return chronoDuration_ < rhs.chronoDuration_;
116+
}
117+
118+
bool operator<=(const HighResTimeDuration& rhs) const {
119+
return chronoDuration_ <= rhs.chronoDuration_;
120+
}
121+
122+
bool operator>(const HighResTimeDuration& rhs) const {
123+
return chronoDuration_ > rhs.chronoDuration_;
124+
}
125+
126+
bool operator>=(const HighResTimeDuration& rhs) const {
127+
return chronoDuration_ >= rhs.chronoDuration_;
128+
}
129+
130+
private:
131+
std::chrono::steady_clock::duration chronoDuration_;
132+
};
133+
134+
/*
135+
* A class representing a specific point in time with high precision.
136+
*
137+
* @see __docs__/README.md for more information.
138+
*/
139+
class HighResTimeStamp {
140+
friend class HighResTimeClock;
141+
friend HighResTimeDuration operator-(
142+
const HighResTimeStamp& lhs,
143+
const HighResTimeStamp& rhs);
144+
friend HighResTimeStamp operator+(
145+
const HighResTimeStamp& lhs,
146+
const HighResTimeDuration& rhs);
147+
friend HighResTimeStamp operator-(
148+
const HighResTimeStamp& lhs,
149+
const HighResTimeDuration& rhs);
150+
151+
public:
152+
HighResTimeStamp()
153+
: chronoTimeStamp_(std::chrono::steady_clock::time_point()) {}
154+
explicit HighResTimeStamp(HighResTimeDuration duration)
155+
: chronoTimeStamp_(duration.chronoDuration_) {}
156+
/* implicit */ HighResTimeStamp(std::chrono::nanoseconds nanoseconds)
157+
: chronoTimeStamp_(nanoseconds) {}
158+
/* implicit */ HighResTimeStamp(std::chrono::microseconds microseconds)
159+
: chronoTimeStamp_(microseconds) {}
160+
/* implicit */ HighResTimeStamp(std::chrono::milliseconds milliseconds)
161+
: chronoTimeStamp_(milliseconds) {}
162+
/* implicit */ HighResTimeStamp(std::chrono::seconds seconds)
163+
: chronoTimeStamp_(seconds) {}
164+
165+
HighResTimeDuration toDuration() const {
166+
return {chronoTimeStamp_.time_since_epoch()};
167+
}
168+
169+
int64_t toNanoseconds() const {
170+
return toDuration().toNanoseconds();
171+
}
172+
173+
int64_t toMicroseconds() const {
174+
return toDuration().toMicroseconds();
175+
}
176+
177+
int64_t toMilliseconds() const {
178+
return toDuration().toMilliseconds();
179+
}
180+
181+
double toDOMHighResTimeStamp() const {
182+
return toDuration().toDOMHighResTimeStamp();
183+
}
184+
185+
bool operator==(const HighResTimeStamp& rhs) const {
186+
return chronoTimeStamp_ == rhs.chronoTimeStamp_;
187+
}
188+
189+
bool operator!=(const HighResTimeStamp& rhs) const {
190+
return chronoTimeStamp_ != rhs.chronoTimeStamp_;
191+
}
192+
193+
bool operator<(const HighResTimeStamp& rhs) const {
194+
return chronoTimeStamp_ < rhs.chronoTimeStamp_;
195+
}
196+
197+
bool operator<=(const HighResTimeStamp& rhs) const {
198+
return chronoTimeStamp_ <= rhs.chronoTimeStamp_;
199+
}
200+
201+
bool operator>(const HighResTimeStamp& rhs) const {
202+
return chronoTimeStamp_ > rhs.chronoTimeStamp_;
203+
}
204+
205+
bool operator>=(const HighResTimeStamp& rhs) const {
206+
return chronoTimeStamp_ >= rhs.chronoTimeStamp_;
207+
}
208+
209+
HighResTimeStamp& operator+=(const HighResTimeDuration& rhs) {
210+
chronoTimeStamp_ += rhs.chronoDuration_;
211+
return *this;
212+
}
213+
214+
HighResTimeStamp& operator-=(const HighResTimeDuration& rhs) {
215+
chronoTimeStamp_ -= rhs.chronoDuration_;
216+
return *this;
217+
}
218+
219+
private:
220+
explicit HighResTimeStamp(std::chrono::steady_clock::time_point timeStamp)
221+
: chronoTimeStamp_(timeStamp) {}
222+
223+
std::chrono::steady_clock::time_point chronoTimeStamp_;
224+
};
225+
226+
/*
227+
* A class providing a monotonic clock that won't be adjusted.
228+
*
229+
* @see __docs__/README.md for more information.
230+
*/
231+
class HighResTimeClock {
232+
public:
233+
static HighResTimeStamp now() noexcept {
234+
return HighResTimeStamp(std::chrono::steady_clock::now());
235+
}
236+
};
237+
238+
inline HighResTimeDuration operator-(
239+
const HighResTimeStamp& lhs,
240+
const HighResTimeStamp& rhs) {
241+
return {lhs.chronoTimeStamp_ - rhs.chronoTimeStamp_};
242+
}
243+
244+
inline HighResTimeStamp operator+(
245+
const HighResTimeStamp& lhs,
246+
const HighResTimeDuration& rhs) {
247+
return HighResTimeStamp(lhs.chronoTimeStamp_ + rhs.chronoDuration_);
248+
}
249+
250+
inline HighResTimeStamp operator-(
251+
const HighResTimeStamp& lhs,
252+
const HighResTimeDuration& rhs) {
253+
return HighResTimeStamp(lhs.chronoTimeStamp_ - rhs.chronoDuration_);
254+
}
255+
33256
} // namespace facebook::react

0 commit comments

Comments
 (0)