Skip to content

It makes startup time significantly longer on Mac #733

Closed
@ShikChen

Description

@ShikChen

Testing environment:

  • macOS 10.14.3
  • Rust 1.32.0
  • rand 0.6.5

Reproduce steps:

  1. cargo new hello
  2. Add rand = "0.6" into dependencies.
  3. Modify main.rs
extern crate rand;

fn main() {
}
  1. cargo build --release

The extern crate rand line makes the running time ~5x slower (measured by hyperfine):

❯ hyperfine --warmup 32 './no-rand' './with-rand'
Benchmark #1: ./no-rand
  Time (mean ± σ):       1.6 ms ±   0.5 ms    [User: 0.8 ms, System: 0.4 ms]
  Range (min … max):     0.9 ms …   5.1 ms    670 runs

  Warning: Command took less than 5 ms to complete. Results might be inaccurate.

Benchmark #2: ./with-rand
  Time (mean ± σ):       7.6 ms ±   0.8 ms    [User: 4.6 ms, System: 2.3 ms]
  Range (min … max):     6.4 ms …  11.3 ms    267 runs

Summary
  './no-rand' ran
    4.87 ± 1.55 times faster than './with-rand'

It looks like most of the time is spent on pre-main stuff:

❯ DYLD_PRINT_STATISTICS=1 ./no-rand
Total pre-main time:   1.19 milliseconds (100.0%)
         dylib loading time:   0.51 milliseconds (42.7%)
        rebase/binding time:   0.05 milliseconds (4.6%)
            ObjC setup time:   0.24 milliseconds (20.1%)
           initializer time:   0.33 milliseconds (28.1%)
           slowest intializers :
             libSystem.B.dylib :   0.27 milliseconds (23.3%)
                libc++.1.dylib :   0.02 milliseconds (2.0%)

❯ DYLD_PRINT_STATISTICS=1 ./with-rand
Total pre-main time:   9.33 milliseconds (100.0%)
         dylib loading time:   2.61 milliseconds (28.0%)
        rebase/binding time:   0.66 milliseconds (7.0%)
            ObjC setup time:   2.46 milliseconds (26.3%)
           initializer time:   3.50 milliseconds (37.5%)
           slowest intializers :
             libSystem.B.dylib :   0.46 milliseconds (5.0%)
                CoreFoundation :   2.34 milliseconds (25.1%)
                    Foundation :   0.24 milliseconds (2.6%)

I tried the same steps on a Linux machine, and there is no issue (always ~1ms). Judged by the above information, I guess the culprit is

#[link(name = "Security", kind = "framework")]
extern {
fn SecRandomCopyBytes(rnd: *const SecRandom,
count: size_t, bytes: *mut u8) -> c_int;
}

It currently blocks me to use rand and some crates that depends on it in a time sensitive application. How can we fix this? Is it ok to use /dev/urandom as the platform source on Mac just like what we did for Linux, instead of linking Security.framework?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions