rust/library/std/src
bors 4cb7ef0f94 Auto merge of #77455 - asm89:faster-spawn, r=kennytm
Use posix_spawn() on unix if program is a path

Previously `Command::spawn` would fall back to the non-posix_spawn based
implementation if the `PATH` environment variable was possibly changed.
On systems with a modern (g)libc `posix_spawn()` can be significantly
faster. If program is a path itself the `PATH` environment variable is
not used for the lookup and it should be safe to use the
`posix_spawnp()` method. [1]

We found this, because we have a cli application that effectively runs a
lot of subprocesses. It would sometimes noticeably hang while printing
output. Profiling showed that the process was spending the majority of
time in the kernel's `copy_page_range` function while spawning
subprocesses. During this time the process is completely blocked from
running, explaining why users were reporting the cli app hanging.

Through this we discovered that `std::process::Command` has a fast and
slow path for process execution. The fast path is backed by
`posix_spawnp()` and the slow path by fork/exec syscalls being called
explicitly. Using fork for process creation is supposed to be fast, but
it slows down as your process uses more memory.  It's not because the
kernel copies the actual memory from the parent, but it does need to
copy the references to it (see `copy_page_range` above!).  We ended up
using the slow path, because the command spawn implementation in falls
back to the slow path if it suspects the PATH environment variable was
changed.

Here is a smallish program demonstrating the slowdown before this code
change:

```
use std::process::Command;
use std::time::Instant;

fn main() {
    let mut args = std::env::args().skip(1);
    if let Some(size) = args.next() {
        // Allocate some memory
        let _xs: Vec<_> = std::iter::repeat(0)
            .take(size.parse().expect("valid number"))
            .collect();

        let mut command = Command::new("/bin/sh");
        command
            .arg("-c")
            .arg("echo hello");

        if args.next().is_some() {
            println!("Overriding PATH");
            command.env("PATH", std::env::var("PATH").expect("PATH env var"));
        }

        let now = Instant::now();
        let child = command
            .spawn()
            .expect("failed to execute process");

        println!("Spawn took: {:?}", now.elapsed());

        let output = child.wait_with_output().expect("failed to wait on process");
        println!("Output: {:?}", output);
    } else {
        eprintln!("Usage: prog [size]");
        std::process::exit(1);
    }
    ()
}
```

Running it and passing different amounts of elements to use to allocate
memory shows that the time taken for `spawn()` can differ quite
significantly. In latter case the `posix_spawnp()` implementation is 30x
faster:

```
$ cargo run --release 10000000
...
Spawn took: 324.275µs
hello
$ cargo run --release 10000000 changepath
...
Overriding PATH
Spawn took: 2.346809ms
hello
$ cargo run --release 100000000
...
Spawn took: 387.842µs
hello
$ cargo run --release 100000000 changepath
...
Overriding PATH
Spawn took: 13.434677ms
hello
```

[1]: 5f72f9800b/posix/execvpe.c (L81)
2020-10-17 06:16:00 +00:00
..
backtrace std: move "mod tests/benches" to separate files 2020-08-31 02:56:59 +00:00
collections Rollup merge of #77072 - sharnoff:hash-docs, r=LukasKalbertodt 2020-10-04 15:45:33 +02:00
env std: move "mod tests/benches" to separate files 2020-08-31 02:56:59 +00:00
error std: move "mod tests/benches" to separate files 2020-08-31 02:56:59 +00:00
f32 std: move "mod tests/benches" to separate files 2020-08-31 02:56:59 +00:00
f64 std: move "mod tests/benches" to separate files 2020-08-31 02:56:59 +00:00
ffi Deny broken intra-doc links in linkchecker 2020-10-15 20:22:16 -04:00
fs std: move "mod tests/benches" to separate files 2020-08-31 02:56:59 +00:00
io Rollup merge of #76084 - Lucretiel:split-buffered, r=dtolnay 2020-10-16 02:10:04 +02:00
lazy std: move "mod tests/benches" to separate files 2020-08-31 02:56:59 +00:00
memchr std: move "mod tests/benches" to separate files 2020-08-31 02:56:59 +00:00
net Parse SocketAddrV6::scope_id 2020-10-06 22:13:15 +00:00
num std: move "mod tests/benches" to separate files 2020-08-31 02:56:59 +00:00
os Take sys/vxworks/{fd,fs,io} from sys/unix instead. 2020-10-16 06:19:00 +02:00
panic review: fix nits and move panic safety tests to the correct place 2020-09-25 23:10:24 +02:00
path std: move "mod tests/benches" to separate files 2020-08-31 02:56:59 +00:00
prelude Fix incorrect link in prelude 2020-09-02 17:38:21 -04:00
process std: move "mod tests/benches" to separate files 2020-08-31 02:56:59 +00:00
sync (docs): make mutex error comment consistent with codebase 2020-10-07 11:48:26 -06:00
sys Auto merge of #77455 - asm89:faster-spawn, r=kennytm 2020-10-17 06:16:00 +00:00
sys_common Rollup merge of #77648 - fusion-engineering-forks:static-mutex, r=dtolnay 2020-10-16 02:10:15 +02:00
thread Rollup merge of #77147 - fusion-engineering-forks:static-mutex, r=dtolnay 2020-10-02 08:25:15 +09:00
time std: move "mod tests/benches" to separate files 2020-08-31 02:56:59 +00:00
alloc.rs Rename AllocErr to AllocError 2020-09-28 14:51:03 -04:00
ascii.rs Convert many files to intra-doc links 2020-09-02 17:37:40 -04:00
backtrace.rs For backtrace, use StaticMutex instead of a raw sys Mutex. 2020-10-07 13:59:03 +02:00
env.rs Improve docs for std::env::args() 2020-09-04 14:00:09 -07:00
error.rs Rename AllocErr to AllocError 2020-09-28 14:51:03 -04:00
f32.rs std: move "mod tests/benches" to separate files 2020-08-31 02:56:59 +00:00
f64.rs std: move "mod tests/benches" to separate files 2020-08-31 02:56:59 +00:00
fs.rs Convert many files to intra-doc links 2020-09-02 17:37:40 -04:00
future.rs Fix stabilization marker for future_readiness_fns 2020-09-15 23:12:08 +02:00
keyword_docs.rs Improve wording for const pointers 2020-09-01 19:44:20 -07:00
lazy.rs Simplify SyncOnceCell's take and drop. 2020-09-12 14:00:38 +02:00
lib.rs stop relying on feature(untagged_unions) in stdlib 2020-10-16 11:33:35 +02:00
macros.rs Add missing links 2020-08-22 20:23:50 -07:00
memchr.rs std: move "mod tests/benches" to separate files 2020-08-31 02:56:59 +00:00
num.rs std: move "mod tests/benches" to separate files 2020-08-31 02:56:59 +00:00
panic.rs review: fix nits and move panic safety tests to the correct place 2020-09-25 23:10:24 +02:00
panicking.rs Abort when catch_unwind catches a foreign exception 2020-08-27 21:08:30 +01:00
path.rs Use intra-doc links for links to module-level docs 2020-10-12 19:22:47 -07:00
primitive_docs.rs Fix link to foreign calling conventions 2020-10-15 00:57:22 -07:00
process.rs Add accessors to Command. 2020-09-26 18:58:38 -07:00
rt.rs Prevent __rust_begin_short_backtrace frames from being tail-call optimised away 2020-08-07 19:31:25 +01:00
time.rs Rollup merge of #76388 - poliorcetics:system-time-document-panic, r=KodrAus 2020-10-06 16:25:53 +09:00