Skip to content

Commit fc259ac

Browse files
committed
update: avoid using Reflection to get Performance each time
1 parent b4c2046 commit fc259ac

File tree

4 files changed

+74
-40
lines changed

4 files changed

+74
-40
lines changed

src/clocks/monotonic/mod.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,16 @@ mod windows;
33
#[cfg(target_os = "windows")]
44
pub use self::windows::Monotonic;
55

6-
#[cfg(target_arch = "wasm32")]
7-
mod wasm;
8-
#[cfg(target_arch = "wasm32")]
9-
pub use self::wasm::Monotonic;
6+
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
7+
mod wasm_browser;
8+
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
9+
pub use self::wasm_browser::Monotonic;
10+
11+
#[cfg(all(target_arch = "wasm32", target_os = "wasi"))]
12+
mod wasm_wasi;
13+
#[cfg(all(target_arch = "wasm32", target_os = "wasi"))]
14+
pub use self::wasm_wasi::Monotonic;
15+
1016

1117
#[cfg(not(any(target_os = "windows", target_arch = "wasm32")))]
1218
mod unix;

src/clocks/monotonic/wasm.rs

Lines changed: 0 additions & 36 deletions
This file was deleted.
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/// Since threads (WebWorkers) in browser don't shared the same memory space, so no objects would have a chance to be sended to other threads, thus it's safe to implement Send for objects here
2+
use web_sys::{
3+
js_sys::Reflect,
4+
wasm_bindgen::{JsCast, JsValue},
5+
Performance,
6+
};
7+
8+
const WASM_MISSING_GLOBAL_THIS_PERF: &str = "failed to find `globalThis.performance`";
9+
const WASM_UNABLE_TO_CAST_PERF: &str =
10+
"Unable to cast `globalThis.performance` to Performance type";
11+
12+
struct PerformanceClassWrapper(Performance);
13+
14+
unsafe impl Send for PerformanceClassWrapper {}
15+
unsafe impl Sync for PerformanceClassWrapper {}
16+
17+
static GLOBAL_PERFORMANCE_INSTANCE: std::sync::OnceLock<PerformanceClassWrapper> =
18+
std::sync::OnceLock::new();
19+
20+
#[derive(Clone, Copy, Debug)]
21+
pub struct Monotonic {
22+
performance: &'static Performance,
23+
}
24+
25+
unsafe impl Send for Monotonic {}
26+
unsafe impl Sync for Monotonic {}
27+
28+
impl Default for Monotonic {
29+
fn default() -> Self {
30+
let performance = GLOBAL_PERFORMANCE_INSTANCE.get_or_init(|| {
31+
PerformanceClassWrapper(
32+
Reflect::get(
33+
&web_sys::js_sys::global(),
34+
&JsValue::from_str("performance"),
35+
)
36+
.expect(WASM_MISSING_GLOBAL_THIS_PERF)
37+
.dyn_into::<Performance>()
38+
.expect(WASM_UNABLE_TO_CAST_PERF),
39+
)
40+
});
41+
42+
Self {
43+
performance: &performance.0,
44+
}
45+
}
46+
}
47+
48+
impl Monotonic {
49+
pub fn now(&self) -> u64 {
50+
let now = self.performance.now();
51+
// `performance.now()` returns the time in milliseconds.
52+
return f64::trunc(now * 1_000_000.0) as u64;
53+
}
54+
}

src/clocks/monotonic/wasm_wasi.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#[derive(Clone, Copy, Debug, Default)]
2+
pub struct Monotonic {
3+
_default: (),
4+
}
5+
6+
impl Monotonic {
7+
pub fn now(&self) -> u64 {
8+
unsafe { wasi::clock_time_get(wasi::CLOCKID_MONOTONIC, 1).expect("failed to get time") }
9+
}
10+
}

0 commit comments

Comments
 (0)