Skip to content

Commit

Permalink
Rework time management (#525)
Browse files Browse the repository at this point in the history
  • Loading branch information
Sytten authored Aug 4, 2024
1 parent c7b8635 commit 925400a
Show file tree
Hide file tree
Showing 14 changed files with 165 additions and 76 deletions.
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions llrt_core/src/module_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ use crate::modules::{
os::OsModule,
path::PathModule,
perf_hooks::PerfHooksModule,
performance,
process::ProcessModule,
timers::TimersModule,
url::UrlModule,
Expand Down Expand Up @@ -88,13 +87,13 @@ impl Default for ModuleBuilder {
.with_global(crate::modules::process::init)
.with_global(crate::modules::navigator::init)
.with_module(UrlModule)
.with_global(performance::init)
.with_global(crate::modules::http::init)
.with_global(crate::modules::exceptions::init)
.with_module(LlrtHexModule)
.with_module(LlrtUuidModule)
.with_module(LlrtXmlModule)
.with_module(PerfHooksModule)
.with_global(crate::modules::perf_hooks::init)
}
}

Expand Down
2 changes: 1 addition & 1 deletion llrt_core/src/modules/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pub use llrt_modules::{buffer, child_process, fs, os, path, perf_hooks, performance, process};
pub use llrt_modules::{buffer, child_process, fs, os, path, perf_hooks, process};

pub mod console;
pub mod crypto;
Expand Down
2 changes: 1 addition & 1 deletion llrt_core/src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ impl Vm {
pub async fn from_options(
vm_options: VmOptions,
) -> StdResult<Self, Box<dyn std::error::Error + Send + Sync>> {
llrt_modules::perf_hooks::init();
llrt_modules::time::init();

SYSTEM_RANDOM
.fill(&mut [0; 8])
Expand Down
7 changes: 1 addition & 6 deletions llrt_modules/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ child-process = ["events", "__stream", "itoa"]
events = []
fs = ["tokio/fs", "llrt_utils/fs", "ring", "buffer", "path"]
os = [
"process",
"libc",
"windows-result",
"windows-registry",
Expand All @@ -34,16 +33,12 @@ os = [
]
path = []
process = []
perf-hooks = ["chrono"]
perf-hooks = []

__bytearray-buffer = ["tokio/sync"]
__stream = ["buffer", "__bytearray-buffer"]

[dependencies]
chrono = { version = "0.4", default-features = false, features = [
"std",
"now",
], optional = true }
either = "1"
itoa = { version = "1", optional = true }
once_cell = { version = "1", optional = true }
Expand Down
5 changes: 2 additions & 3 deletions llrt_modules/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,15 @@
#![allow(clippy::new_without_default)]
pub use self::module_info::ModuleInfo;
pub use self::modules::*;
use std::sync::atomic::AtomicUsize;

mod module_info;
mod modules;
#[cfg(feature = "__stream")]
pub mod stream;
mod sysinfo;
#[cfg(test)]
mod test;
pub mod time;
mod utils;

pub const VERSION: &str = env!("CARGO_PKG_VERSION");

pub static TIME_ORIGIN: AtomicUsize = AtomicUsize::new(0);
2 changes: 0 additions & 2 deletions llrt_modules/src/modules/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,5 @@ pub mod os;
pub mod path;
#[cfg(feature = "perf-hooks")]
pub mod perf_hooks;
#[cfg(feature = "perf-hooks")]
pub mod performance;
#[cfg(feature = "process")]
pub mod process;
2 changes: 1 addition & 1 deletion llrt_modules/src/modules/os/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use self::unix::{get_release, get_type, get_version};
#[cfg(windows)]
use self::windows::{get_release, get_type, get_version};
use crate::module_info::ModuleInfo;
use crate::process::get_platform;
use crate::sysinfo::get_platform;

#[cfg(unix)]
mod unix;
Expand Down
38 changes: 19 additions & 19 deletions llrt_modules/src/modules/perf_hooks.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,29 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
use crate::{ModuleInfo, TIME_ORIGIN};
use chrono::Utc;
use std::sync::atomic::Ordering;

use llrt_utils::module::export_default;
use rquickjs::{
atom::PredefinedAtom,
module::{Declarations, Exports, ModuleDef},
prelude::Func,
Ctx, Object, Result,
};
use std::sync::atomic::Ordering;

use crate::{time, ModuleInfo};

fn get_time_origin() -> f64 {
let time_origin = TIME_ORIGIN.load(Ordering::Relaxed) as f64;
let time_origin = time::TIME_ORIGIN.load(Ordering::Relaxed) as f64;

time_origin / 1e6
}

fn now() -> f64 {
let now = Utc::now().timestamp_nanos_opt().unwrap_or_default() as f64;
let started = TIME_ORIGIN.load(Ordering::Relaxed) as f64;
let now = time::now_nanos();
let started = time::TIME_ORIGIN.load(Ordering::Relaxed);
let elapsed = now.checked_sub(started).unwrap_or_default();

(now - started) / 1e6
(elapsed as f64) / 1e6
}

fn to_json(ctx: Ctx<'_>) -> Result<Object<'_>> {
Expand All @@ -32,15 +34,7 @@ fn to_json(ctx: Ctx<'_>) -> Result<Object<'_>> {
Ok(obj)
}

// For accuracy reasons, this function should be executed when the vm is initialized
pub fn init() {
if TIME_ORIGIN.load(Ordering::Relaxed) == 0 {
let time_origin = Utc::now().timestamp_nanos_opt().unwrap_or_default() as usize;
TIME_ORIGIN.store(time_origin, Ordering::Relaxed)
}
}

pub(crate) fn new_performance(ctx: Ctx<'_>) -> Result<Object<'_>> {
fn new_performance(ctx: Ctx<'_>) -> Result<Object<'_>> {
let global = ctx.globals();
global.get("performance").or_else(|_| {
let performance = Object::new(ctx)?;
Expand Down Expand Up @@ -78,14 +72,20 @@ impl From<PerfHooksModule> for ModuleInfo<PerfHooksModule> {
}
}
}

pub fn init(ctx: &Ctx<'_>) -> Result<()> {
new_performance(ctx.clone())?;
Ok(())
}

#[cfg(test)]
mod tests {
use super::*;
use crate::test::{call_test, test_async_with, ModuleEvaluator};

#[tokio::test]
async fn test_now() {
init();
time::init();
test_async_with(|ctx| {
Box::pin(async move {
ModuleEvaluator::eval_rust::<PerfHooksModule>(ctx.clone(), "perf_hooks")
Expand Down Expand Up @@ -118,7 +118,7 @@ mod tests {

#[tokio::test]
async fn test_time_origin() {
init();
time::init();
test_async_with(|ctx| {
Box::pin(async move {
ModuleEvaluator::eval_rust::<PerfHooksModule>(ctx.clone(), "perf_hooks")
Expand Down Expand Up @@ -147,7 +147,7 @@ mod tests {

#[tokio::test]
async fn test_to_json() {
init();
time::init();
test_async_with(|ctx| {
Box::pin(async move {
ModuleEvaluator::eval_rust::<PerfHooksModule>(ctx.clone(), "perf_hooks")
Expand Down
9 changes: 0 additions & 9 deletions llrt_modules/src/modules/performance.rs

This file was deleted.

115 changes: 85 additions & 30 deletions llrt_modules/src/modules/process.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
use crate::{ModuleInfo, TIME_ORIGIN, VERSION};
use chrono::Utc;
use std::env;
use std::{collections::HashMap, sync::atomic::Ordering};

use llrt_utils::{module::export_default, result::ResultExt};
use rquickjs::{
atom::PredefinedAtom,
Expand All @@ -12,49 +13,29 @@ use rquickjs::{
prelude::Func,
Array, BigInt, Ctx, Function, IntoJs, Object, Result, Value,
};
use std::env;
use std::{collections::HashMap, sync::atomic::Ordering};

pub fn get_platform() -> &'static str {
let platform = env::consts::OS;
match platform {
"macos" => "darwin",
"windows" => "win32",
_ => platform,
}
}
pub use crate::sysinfo::{get_arch, get_platform};
use crate::{time, ModuleInfo, VERSION};

fn cwd(ctx: Ctx<'_>) -> Result<rquickjs::String<'_>> {
env::current_dir()
.or_throw(&ctx)
.and_then(|path| rquickjs::String::from_str(ctx, path.to_string_lossy().as_ref()))
}

pub fn get_arch() -> &'static str {
let arch = env::consts::ARCH;

match arch {
"x86_64" | "x86" => return "x64",
"aarch64" => return "arm64",
_ => (),
}

arch
}

fn hr_time_big_int(ctx: Ctx<'_>) -> Result<BigInt> {
let now = Utc::now().timestamp_nanos_opt().unwrap_or_default() as u64;
let started = TIME_ORIGIN.load(Ordering::Relaxed) as u64;
let now = time::now_nanos();
let started = time::TIME_ORIGIN.load(Ordering::Relaxed);

let elapsed = now - started;
let elapsed = now.checked_sub(started).unwrap_or_default();

BigInt::from_u64(ctx, elapsed)
}

fn hr_time(ctx: Ctx<'_>) -> Result<Array<'_>> {
let now = Utc::now().timestamp_nanos_opt().unwrap_or_default() as u64;
let started = TIME_ORIGIN.load(Ordering::Relaxed) as u64;
let elapsed = now - started;
let now = time::now_nanos();
let started = time::TIME_ORIGIN.load(Ordering::Relaxed);
let elapsed = now.checked_sub(started).unwrap_or_default();

let seconds = elapsed / 1_000_000_000;
let remaining_nanos = elapsed % 1_000_000_000;
Expand Down Expand Up @@ -174,3 +155,77 @@ impl From<ProcessModule> for ModuleInfo<ProcessModule> {
}
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::test::{call_test, test_async_with, ModuleEvaluator};

#[tokio::test]
async fn test_hr_time() {
time::init();
test_async_with(|ctx| {
Box::pin(async move {
init(&ctx).unwrap();
ModuleEvaluator::eval_rust::<ProcessModule>(ctx.clone(), "process")
.await
.unwrap();

let module = ModuleEvaluator::eval_js(
ctx.clone(),
"test",
r#"
import { hrtime } from 'process';
export async function test() {
// TODO: Delaying with setTimeout
for(let i=0; i < (1<<20); i++){}
return hrtime()
}
"#,
)
.await
.unwrap();
let result = call_test::<Vec<u32>, _>(&ctx, &module, ()).await;
assert_eq!(result.len(), 2);
assert_eq!(result[0], 0);
assert!(result[1] > 0);
})
})
.await;
}

#[tokio::test]
async fn test_hr_time_bigint() {
time::init();
test_async_with(|ctx| {
Box::pin(async move {
init(&ctx).unwrap();
ModuleEvaluator::eval_rust::<ProcessModule>(ctx.clone(), "process")
.await
.unwrap();

let module = ModuleEvaluator::eval_js(
ctx.clone(),
"test",
r#"
import { hrtime } from 'process';
export async function test() {
// TODO: Delaying with setTimeout
for(let i=0; i < (1<<20); i++){}
return hrtime.bigint()
}
"#,
)
.await
.unwrap();
let result = call_test::<Coerced<i64>, _>(&ctx, &module, ()).await;
assert!(result.0 > 0);
})
})
.await;
}
}
22 changes: 22 additions & 0 deletions llrt_modules/src/sysinfo.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use std::env;

pub fn get_platform() -> &'static str {
let platform = env::consts::OS;
match platform {
"macos" => "darwin",
"windows" => "win32",
_ => platform,
}
}

pub fn get_arch() -> &'static str {
let arch = env::consts::ARCH;

match arch {
"x86_64" | "x86" => return "x64",
"aarch64" => return "arm64",
_ => (),
}

arch
}
Loading

0 comments on commit 925400a

Please sign in to comment.