Skip to content

tokio::time::sleep has ~19ms overhead on BSD #8121

@WhyNotHugo

Description

@WhyNotHugo

Version

bsd_timer_reproducer v0.1.0 (/tmp/minimal_reproducer)
└── tokio v1.52.2
    ├── bytes v1.11.1
    ├── libc v0.2.186
    ├── mio v1.2.0
    │   └── libc v0.2.186
    ├── parking_lot v0.12.5
    │   ├── lock_api v0.4.14
    │   │   └── scopeguard v1.2.0
    │   └── parking_lot_core v0.9.12
    │       ├── cfg-if v1.0.4
    │       ├── libc v0.2.186
    │       └── smallvec v1.15.1
    ├── pin-project-lite v0.2.17
    ├── signal-hook-registry v1.4.8
    │   ├── errno v0.3.14
    │   │   └── libc v0.2.186
    │   └── libc v0.2.186
    ├── socket2 v0.6.3
    │   └── libc v0.2.186
    └── tokio-macros v2.7.0 (proc-macro)
        ├── proc-macro2 v1.0.106
        │   └── unicode-ident v1.0.24
        ├── quote v1.0.45
        │   └── proc-macro2 v1.0.106 (*)
        └── syn v2.0.117
            ├── proc-macro2 v1.0.106 (*)
            ├── quote v1.0.45 (*)
            └── unicode-ident v1.0.24

I originally reproduced this with an older version of tokio; it doesn't seem to be a recent bug.

Platform

BSD. uname -a yields OpenBSD prophecy.whynothugo.nl 7.8 GENERIC.MP#54 amd64

Description

tokio::time::sleep has an ~19ms overhead. When sleeping for short amounts of time (e.g.: in the order of 30ms), this completely breaks any logic relying on sleep.

I tried this code:

use std::time::Duration;
use tokio::time::{sleep, Instant};

#[tokio::main]
async fn main() {
    let timeout = Duration::from_millis(40);

    println!("Running {}ms timers.", timeout.as_millis());
    for _run in 1..=10 {
        let start = Instant::now();
        sleep(timeout).await;
        let end = Instant::now();

        println!("duration: {}ms", end.duration_since(start).as_millis());
    }

}

I expected to see this happen: durations of aprox 40ms.

Instead, this happened: sample output:

Running 40ms timers.
duration: 53ms
duration: 59ms
duration: 59ms
duration: 59ms
duration: 59ms
duration: 60ms
duration: 49ms
duration: 59ms
duration: 60ms
duration: 59ms

I'm reproducing this on a i7-13700K.

The overhead seems to be fixed, so a 15ms sleep will sleep 25–30ms:

Running 15ms timers.
duration: 25ms
duration: 29ms
duration: 20ms
duration: 29ms
duration: 29ms
duration: 29ms
duration: 30ms
duration: 30ms
duration: 29ms
duration: 20ms

For reference, attempting to render at 60fps would require submitting frames every 16ms. The overhead in sleep already blows 118% of that budget.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-tokioArea: The main tokio crateC-bugCategory: This is a bug.M-timeModule: tokio/time

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions