summaryrefslogtreecommitdiff
path: root/ext/web
diff options
context:
space:
mode:
Diffstat (limited to 'ext/web')
-rw-r--r--ext/web/02_timers.js9
-rw-r--r--ext/web/benches/timers_ops.rs10
-rw-r--r--ext/web/lib.rs2
-rw-r--r--ext/web/timers.rs32
4 files changed, 40 insertions, 13 deletions
diff --git a/ext/web/02_timers.js b/ext/web/02_timers.js
index 07b9587ea..f703120e6 100644
--- a/ext/web/02_timers.js
+++ b/ext/web/02_timers.js
@@ -13,6 +13,7 @@
MapPrototypeGet,
MapPrototypeHas,
MapPrototypeSet,
+ Uint32Array,
// deno-lint-ignore camelcase
NumberPOSITIVE_INFINITY,
PromisePrototypeThen,
@@ -25,8 +26,14 @@
const { reportException } = window.__bootstrap.event;
const { assert } = window.__bootstrap.infra;
+ let hr;
function opNow() {
- return ops.op_now();
+ if (!hr) {
+ hr = new Uint32Array(2);
+ ops.op_now_set_buf(hr);
+ }
+ ops.op_now.fast();
+ return (hr[0] * 1000 + hr[1] / 1e6);
}
// ---------------------------------------------------------------------------
diff --git a/ext/web/benches/timers_ops.rs b/ext/web/benches/timers_ops.rs
index f5d03d6c3..10b434015 100644
--- a/ext/web/benches/timers_ops.rs
+++ b/ext/web/benches/timers_ops.rs
@@ -1,8 +1,8 @@
use deno_core::Extension;
+use deno_bench_util::bench_js_async;
use deno_bench_util::bench_or_profile;
use deno_bench_util::bencher::{benchmark_group, Bencher};
-use deno_bench_util::{bench_js_async, bench_js_sync};
use deno_web::BlobStore;
struct Permissions;
@@ -27,7 +27,7 @@ fn setup() -> Vec<Extension> {
Extension::builder()
.js(vec![
("setup", r#"
- const { opNow, setTimeout, handleTimerMacrotask } = globalThis.__bootstrap.timers;
+ const { setTimeout, handleTimerMacrotask } = globalThis.__bootstrap.timers;
Deno.core.setMacrotaskCallback(handleTimerMacrotask);
"#),
])
@@ -39,13 +39,9 @@ fn setup() -> Vec<Extension> {
]
}
-fn bench_op_now(b: &mut Bencher) {
- bench_js_sync(b, r#"opNow();"#, setup);
-}
-
fn bench_set_timeout(b: &mut Bencher) {
bench_js_async(b, r#"setTimeout(() => {}, 0);"#, setup);
}
-benchmark_group!(benches, bench_op_now, bench_set_timeout,);
+benchmark_group!(benches, bench_set_timeout,);
bench_or_profile!(benches);
diff --git a/ext/web/lib.rs b/ext/web/lib.rs
index a80447614..91c680f5f 100644
--- a/ext/web/lib.rs
+++ b/ext/web/lib.rs
@@ -51,6 +51,7 @@ pub use crate::message_port::JsMessageData;
pub use crate::message_port::MessagePort;
use crate::timers::op_now;
+use crate::timers::op_now_set_buf;
use crate::timers::op_sleep;
use crate::timers::op_timer_handle;
use crate::timers::StartTime;
@@ -106,6 +107,7 @@ pub fn init<P: TimersPermission + 'static>(
compression::op_compression_new::decl(),
compression::op_compression_write::decl(),
compression::op_compression_finish::decl(),
+ op_now_set_buf::decl(),
op_now::decl::<P>(),
op_timer_handle::decl(),
op_cancel_handle::decl(),
diff --git a/ext/web/timers.rs b/ext/web/timers.rs
index 0f781a579..d9ceef875 100644
--- a/ext/web/timers.rs
+++ b/ext/web/timers.rs
@@ -4,6 +4,7 @@
use deno_core::error::AnyError;
use deno_core::op;
+use deno_core::ZeroCopyBuf;
use deno_core::CancelFuture;
use deno_core::CancelHandle;
@@ -23,29 +24,50 @@ pub trait TimersPermission {
pub type StartTime = Instant;
+static mut NOW_BUF: *mut u32 = std::ptr::null_mut();
+
+#[op]
+pub fn op_now_set_buf(buf: ZeroCopyBuf) {
+ assert_eq!(buf.len(), 8);
+ // SAFETY: This is safe because this is the only place where we initialize
+ // NOW_BUF.
+ unsafe {
+ NOW_BUF = buf.as_ptr() as *mut u32;
+ }
+}
+
// Returns a milliseconds and nanoseconds subsec
// since the start time of the deno runtime.
// If the High precision flag is not set, the
// nanoseconds are rounded on 2ms.
-#[op]
-pub fn op_now<TP>(state: &mut OpState) -> f64
+#[op(fast)]
+pub fn op_now<TP>(state: &mut OpState)
where
TP: TimersPermission + 'static,
{
let start_time = state.borrow::<StartTime>();
let elapsed = start_time.elapsed();
let seconds = elapsed.as_secs();
- let mut subsec_nanos = elapsed.subsec_nanos() as f64;
- let reduced_time_precision = 2_000_000.0; // 2ms in nanoseconds
+ let mut subsec_nanos = elapsed.subsec_nanos();
// If the permission is not enabled
// Round the nano result on 2 milliseconds
// see: https://developer.mozilla.org/en-US/docs/Web/API/DOMHighResTimeStamp#Reduced_time_precision
if !state.borrow_mut::<TP>().allow_hrtime() {
+ let reduced_time_precision = 2_000_000; // 2ms in nanoseconds
subsec_nanos -= subsec_nanos % reduced_time_precision;
}
- (seconds * 1_000) as f64 + (subsec_nanos / 1_000_000.0)
+ // SAFETY: This is safe because we initialize NOW_BUF in op_now_set_buf, its a null pointer
+ // otherwise.
+ // op_now_set_buf guarantees that the buffer is 8 bytes long.
+ unsafe {
+ if !NOW_BUF.is_null() {
+ let buf = std::slice::from_raw_parts_mut(NOW_BUF, 2);
+ buf[0] = seconds as u32;
+ buf[1] = subsec_nanos as u32;
+ }
+ }
}
pub struct TimerHandle(Rc<CancelHandle>);