Giter Site home page Giter Site logo

rust-coarsetime's Introduction

Documentation Windows build status

coarsetime

A Rust crate to make time measurements, that focuses on speed.

This crate is a partial replacement for the Time and Duration structures from the standard library, with the following differences:

  • Speed is privileged over accuracy. In particular, CLOCK_MONOTONIC_COARSE is used to retrieve the clock value on Linux systems, and transformations avoid operations that can be slow on non-Intel systems.
  • The number of system calls can be kept to a minimum. The "most recent timestamp" is always kept in memory. It can be read with just a load operation, and can be updated only as frequently as necessary.

Installation

coarsetime is available on crates.io and works on Rust stable, beta, and nightly.

Windows and Unix-like systems are supported.

Available feature:

  • wasi-abi2: when targeting WASI, use the second preview of the ABI. Default is to use the regular WASI-core ABI.

Documentation

API documentation

Example

extern crate coarsetime;

use coarsetime::{Duration, Instant, Updater};

// Get the current instant. This may require a system call, but it may also
// be faster than the stdlib equivalent.
let now = Instant::now();

// Get the latest known instant. This operation is super fast.
// In this case, the value will be identical to `now`, because we haven't
// updated the latest known instant yet.
let ts1 = Instant::recent();

// Update the latest known instant. This may require a system call.
// Note that a call to `Instant::now()` also updates the stored instant.
Instant::update();

// Now, we may get a different instant. This call is also super fast.
let ts2 = Instant::recent();

// Compute the time elapsed between ts2 and ts1.
let elapsed_ts2_ts1 = ts2.duration_since(ts1);

// Operations such as `+` and `-` between `Instant` and `Duration` are also
// available.
let elapsed_ts2_ts1 = ts2 - ts1;

// Returns the time elapsed since ts1.
// This retrieves the actual current time, and may require a system call.
let elapsed_since_ts1 = ts1.elapsed();

// Returns the approximate time elapsed since ts1.
// This uses the latest known instant, and is super fast.
let elapsed_since_recent = ts1.elapsed_since_recent();

// Instant::update() should be called periodically, for example using an
// event loop. Alternatively, the crate provides an easy way to spawn a
// background task that will periodically update the latest known instant.
// Here, the update will happen every 250ms.
let updater = Updater::new(250).start().unwrap();

// From now on, Instant::recent() will always return an approximation of the
// current instant.
let ts3 = Instant::recent();

// Stop the task.
updater.stop().unwrap();

// Returns the elapsed time since the UNIX epoch
let unix_timestamp = Clock::now_since_epoch();

// Returns an approximation of the elapsed time since the UNIX epoch, based on
// the latest time update
let unix_timestamp_approx = Clock::recent_since_epoch();

rust-coarsetime's People

Contributors

beltram avatar dependabot-preview[bot] avatar dragostis avatar drahnr avatar ijackson avatar jedisct1 avatar kubo39 avatar nmathewson avatar zhongzc avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

rust-coarsetime's Issues

Use std::time::Duration?

Looks like the Duration introduced by this crate can be replaced by std::time::Duration instead. There is no extra cost when the user does not use the Duration.

Overflow possibilities in helpers.rs

I was looking at the code in helpers.rs with a view to excluding panics (see #20, also #29).

I noticed that these functions all use << to shift some number of seconds into the top half of the u64. However, if the number of seconds is too large, this will simply discard the top bits.

I think this is all correct for Instant unless the whole program runs for more than 2^32 seconds, so that's fine.

But it's wrong for Duration. For example, currently, Duration::from_secs(4294967296) is zero. (And the conversion from std::time::Duration is similarly troubled.)

Based on your opinion on #29, I guess you think that Duration::from_secs(4294967296) and Duration::from(std::time::Duration::from_secs()) should both panic? Then, presumably, there should be Duration::from_std_saturating?

I think conversions from coarsetime::Duration to std::time::Duration are correct and infallible but I'm not 100% sure. Perhaps there should be some test cases for that.

Please let me know what you think.

Runtime errors in wasm32-freestanding

PROBLEM:
coarsetime v0.1.28 relies on an implementation of time that is not supported in all WASM environments (I haven't tested node, but I produced this issue within a browser runtime)

At runtime you get errors that look like:

    error output:
        panicked at library/std/src/sys/wasm/../unsupported/time.rs:31:9:
        time not implemented on this platform

SOLUTION:
I was able to get my code compiling and tests passing by specifying:

jwt-simple = "0.11.6"
coarsetime = { version = "=0.1.23" }

OBSERVATIONS:
I also confirmed that setting

jwt-simple = "0.11.6"

and coarsetime to 1.27, 1.26, 1.25, or 1.24 doesn't compile.

TAKEAWAYS:
Therefore I am fairly confident at v0.11.7 just doesn't work in (at the very least) the browser, no matter how you configure coarsetime; and that v0.11.6 was the last viable version for using this library in wasm, so long as you set:

coarsetime = "=0.1.23"

SUGGESTIONS:

yank v0.11.7 and in v0.11.6 specify

coarsetime = "=0.1.23"

not

coarsetime = "^0.1.23"

in the Cargo.toml

If you advertise WASM compatibility in your docs:

jwt-simple uses only pure Rust implementations, and can be compiled out of the box to WebAssembly/WASI

write tests that compile to and run within a WASM runtime.

Panic when with target wasm32-wasi

Hi i am using the https://github.com/jedisct1/rust-jwt-simple library for my Envoy wasm filter. I am using wasm32-wasi as a target. Seems like this library panics when getting the current time with:

[source/extensions/common/wasm/context.cc:1180] wasm log: panicked at 'Clock not available: Error { code: 58, name: "NOTSUP", message: "Not supported, or operation not supported on socket." }', /Users/sondre/.cargo/registry/src/github.com-1ecc6299db9ec823/coarsetime-0.1.18/src/instant.rs:164:67

Are you aware of this issue with the wasm32-wasi target?

Expose from_u64 and as_u64 APIs?

Hello!

I have a use in case where I need to update an atomic timer every time a given event occurs. To do that, I'm using an AtomicU64, and coarsetime::Instant::as_u64(). That latter API is not publicly documented, however, which implies that it might go away in the future.

Would you be open to a patch that would document and stabilize the APIs that convert Instant and Duration values to and from u64? Or if you think that's a bad idea, would you be open to a patch to add an AtomicInstant type?

Crate won't compile for `x86_64-fortanix-unknown-sgx` target

coarsetime won't compile for target x86_64-fortanix-unknown-sgx

error: could not compile `coarsetime` due to 4 previous errors
warning: build failed, waiting for other jobs to finish...
error[E0599]: no associated item named `_now` found for struct `instant::Instant` in the current scope
  --> /sources/coarsetime-0.1.22/src/instant.rs:60:25
   |
19 | pub struct Instant(u64);
   | ------------------------ associated item `_now` not found for this
...
60 |         let now = Self::_now();
   |                         ^^^^
   |                         |
   |                         associated item not found in `instant::Instant`
   |                         help: there is an associated function with a similar name: `now`


error[E0599]: no associated item named `_now` found for struct `instant::Instant` in the current scope
  --> /sources/coarsetime-0.1.22/src/instant.rs:78:25
   |
19 | pub struct Instant(u64);
   | ------------------------ associated item `_now` not found for this
...
78 |         let now = Self::_now();
   |                         ^^^^
   |                         |
   |                         associated item not found in `instant::Instant`
   |                         help: there is an associated function with a similar name: `now`


error[E0599]: no associated item named `_now` found for struct `instant::Instant` in the current scope
   --> /sources/coarsetime-0.1.22/src/instant.rs:207:29
    |
19  | pub struct Instant(u64);
    | ------------------------ associated item `_now` not found for this
...
207 |             let now = Self::_now();
    |                             ^^^^
    |                             |
    |                             associated item not found in `instant::Instant`
    |                             help: there is an associated function with a similar name: `now`


error: aborting due to 3 previous errors


For more information about this error, try `rustc --explain E0599`.

Relevant for https://github.com/jedisct1/rust-jwt-simple/issues/66

`time` crate conversion slower on some platforms

I was considering using this crate for faster time lookups since I'm writing a language runtime that has some nontrivial time-based scheduling logic. I need sub-millisecond precision, so I can't actually use the coarse/recent time features in this crate, but this crate also claimed to have faster lookups of the real current time. Specifically I need to create an instance of the OffsetDateTime type from the no-std compatible time crate. But it looks like using this crate as the time source is actually slower on some platforms:

#![feature(test)]

use time::{OffsetDateTime, UtcOffset};

pub fn old_way(utc_offset: UtcOffset) -> OffsetDateTime {
    OffsetDateTime::now_utc().to_offset(utc_offset)
}
pub fn new_way(utc_offset: UtcOffset) -> OffsetDateTime {
    let t = coarsetime::Clock::now_since_epoch();
    OffsetDateTime::from_unix_timestamp_nanos(t.as_nanos() as i128).unwrap()
}

#[cfg(test)]
mod tests {
    use crate::*;
    extern crate test;
    use test::{Bencher, black_box};

    #[bench]
    fn bench_old_way(b: &mut Bencher) {
        b.iter(|| {
            black_box(old_way(UtcOffset::UTC));
        });
    }

    #[bench]
    fn bench_new_way(b: &mut Bencher) {
        b.iter(|| {
            black_box(new_way(UtcOffset::UTC));
        });
    }
}

And I got the following results on raspberry pi:

running 2 tests
test tests::bench_new_way ... bench:       1,326 ns/iter (+/- 6)
test tests::bench_old_way ... bench:         527 ns/iter (+/- 4)

I realize this isn't this crate's fault, rather the combined behavior of the two, but is there some more efficient way to go about this specific use case? Or, since it's practically the de-facto standard, can support for the time crate be added in this crate as an optional feature to bypass some of the inefficiencies in the conversion?

Raw API for getting Instant::now without updating/reading cache

As far as I can see there is no way to get the current instant without interacting with the RECENT cache (load or store). It would be nice to add that. I have no intention of using the cache but Instant::now() does a useless atomic relaxed store on every call.

Essentially, I'm asking to have Instant::_now be exposed in the public API (under a better name, of course).

CI fails due to problems with `precision`

From CI in #29
https://ci.appveyor.com/project/jedisct1/rust-coarsetime/builds/49453086/job/arpwy1tk0r20uhg3

   Compiling precision v0.1.16
error: type `u64` cannot be used with this register class

And https://ci.appveyor.com/project/jedisct1/rust-coarsetime/builds/49453086/job/ybbn6w17gpoonm31

The following warnings were emitted during compilation:
warning: [email protected]: Failed to run: "gcc.exe" "--version"
warning: [email protected]: Failed to run: "gcc.exe" "--version"
error: failed to run custom build command for `precision v0.1.16`
Caused by:
  process didn't exit successfully: `C:\projects\rust-coarsetime\target\debug\build\precision-4c76a1535f82466e\build-script-build` (exit code: 1)

I see similar trouble in some of my other MRs.

Add `Duration::as_millis()`?

It seems to lack this commonly used function. By calling both Duration::as_secs() and Duration::subsec_nanos() can construct a millis but, IMO, it not good as just Duration::as_millis().

Potentially replace AtomicU64

Since 64 bit stores on 32 bit machines may not be atomic, the use of AtomicU64 is mandated, but a potential solution to the issue of nightly requirement could be using AtomicOption instead.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.