Time
Joule provides two types for time measurement: Duration for time spans and Instant for timestamps.
Duration
A time span measured in nanoseconds. All arithmetic is exact — no floating-point rounding.
Creating Durations
let d1 = Duration::from_secs(5); // 5 seconds
let d2 = Duration::from_millis(1500); // 1.5 seconds
let d3 = Duration::from_micros(250); // 250 microseconds
let d4 = Duration::from_nanos(100); // 100 nanoseconds
Querying
let d = Duration::from_millis(2500);
d.as_secs(); // 2
d.as_millis(); // 2500
d.as_micros(); // 2500000
d.as_nanos(); // 2500000000
d.is_zero(); // false
Arithmetic
let a = Duration::from_secs(3);
let b = Duration::from_millis(500);
let sum = a.add(&b); // 3.5 seconds
let diff = a.sub(&b); // 2.5 seconds
let doubled = a.mul(2); // 6 seconds
let halved = a.div(2); // 1.5 seconds
// Checked arithmetic (returns Option)
let safe = a.checked_add(&b); // Option::Some(3.5s)
let over = a.checked_sub(&Duration::from_secs(10)); // Option::None
Instant
A monotonic timestamp. Cannot go backwards. Used for measuring elapsed time.
Measuring Elapsed Time
let start = Instant::now(); // 15.0 pJ — reads system clock
// ... do work ...
heavy_computation();
let elapsed: Duration = start.elapsed();
println!("Took {} ms", elapsed.as_millis());
Comparing Instants
let t1 = Instant::now();
// ... work ...
let t2 = Instant::now();
let gap: Duration = t2.duration_since(&t1);
Example: Benchmarking with Energy
#[energy_budget(max_joules = 0.001)]
fn timed_sort(data: Vec<i32>) -> (Vec<i32>, Duration) {
let start = Instant::now();
let sorted = sort(data);
let elapsed = start.elapsed();
(sorted, elapsed)
}
fn main() {
let data = vec![5, 3, 1, 4, 2, 8, 7, 6];
let (sorted, time) = timed_sort(data);
println!("Sorted in {} us", time.as_micros());
}
Energy Costs
| Operation | Cost | Notes |
|---|---|---|
Duration arithmetic | 0.05 pJ | Integer add/sub |
Instant::now() | 15.0 pJ | System clock read (syscall) |
elapsed() | 15.0 pJ | Clock read + subtraction |
duration_since() | 0.05 pJ | Integer subtraction |
Instant::now() is the expensive operation — it requires a system call (clock_gettime on Linux, mach_absolute_time on macOS). Avoid calling it in tight loops. Measure coarse-grained sections instead.