Skip to content

Commit

Permalink
Implement re_tuid::Tuid::random() on web (#1796)
Browse files Browse the repository at this point in the history
* Implement `re_tuid::Tuid::random()` on web

* Fix bad error message
  • Loading branch information
emilk authored Apr 8, 2023
1 parent 8ab1155 commit 880cf8e
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 21 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

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

6 changes: 2 additions & 4 deletions crates/re_tuid/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,15 @@ serde = ["dep:serde"]

[dependencies]
document-features = "0.2"
getrandom = "0.2"
instant = "0.1"
once_cell = "1.16"

# Optional dependencies:
arrow2 = { workspace = true, optional = true } # used by arrow2_convert
arrow2_convert = { workspace = true, optional = true }
serde = { version = "1", features = ["derive"], optional = true }

# native dependencies:
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
getrandom = "0.2"

[dev-dependencies]
criterion = "0.4"

Expand Down
37 changes: 20 additions & 17 deletions crates/re_tuid/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ impl Tuid {
};

#[inline]
#[cfg(not(target_arch = "wasm32"))] // TODO(emilk): implement for wasm32 (needs ms since epoch).
pub fn random() -> Self {
use std::cell::RefCell;

Expand Down Expand Up @@ -106,35 +105,39 @@ impl Tuid {

/// Returns a high-precision, monotonically increasing count that approximates nanoseconds since unix epoch.
#[inline]
#[cfg(not(target_arch = "wasm32"))]
fn monotonic_nanos_since_epoch() -> u64 {
// This can maybe be optimized
use instant::Instant;
use once_cell::sync::Lazy;
use std::time::Instant;

fn epoch_offset_and_start() -> (u64, Instant) {
if let Ok(duration_since_epoch) = std::time::UNIX_EPOCH.elapsed() {
let nanos_since_epoch = duration_since_epoch.as_nanos() as u64;
(nanos_since_epoch, Instant::now())
} else {
// system time is set before 1970. this should be quite rare.
(0, Instant::now())
}
}

static START_TIME: Lazy<(u64, Instant)> = Lazy::new(epoch_offset_and_start);
static START_TIME: Lazy<(u64, Instant)> = Lazy::new(|| (nanos_since_epoch(), Instant::now()));
START_TIME.0 + START_TIME.1.elapsed().as_nanos() as u64
}

fn nanos_since_epoch() -> u64 {
if let Ok(duration_since_epoch) = instant::SystemTime::UNIX_EPOCH.elapsed() {
let mut nanos_since_epoch = duration_since_epoch.as_nanos() as u64;

if cfg!(target_arch = "wasm32") {
// Web notriously round to the nearest millisecond (because of spectre/meltdown)
// so we add a bit of extra randomenss here to increase our entropy and reduce the chance of collisions:
nanos_since_epoch += random_u64() % 1_000_000;
}

nanos_since_epoch
} else {
// system time is set before 1970. this should be quite rare.
0
}
}

#[inline]
#[cfg(not(target_arch = "wasm32"))]
fn random_u64() -> u64 {
let mut bytes = [0_u8; 8];
getrandom::getrandom(&mut bytes).expect("Couldn't get inc");
getrandom::getrandom(&mut bytes).expect("Couldn't get random bytes");
u64::from_le_bytes(bytes)
}

#[cfg(not(target_arch = "wasm32"))]
#[test]
fn test_tuid() {
use std::collections::{BTreeSet, HashSet};
Expand Down

0 comments on commit 880cf8e

Please sign in to comment.