Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce CString allocations in std as much as possible #93668

Merged
merged 1 commit into from
Oct 9, 2022

Conversation

SUPERCILEX
Copy link
Contributor

@SUPERCILEX SUPERCILEX commented Feb 5, 2022

Currently, every operation involving paths in fs allocates memory to hold the path before sending it through the syscall. This PR instead uses a stack allocation (chosen size is somewhat arbitrary) when the path is short before falling back to heap allocations for long paths.

Benchmarks show that the stack allocation is ~2x faster for short paths:

test sys::unix::fd::tests::bench_heap_path_alloc                  ... bench:          34 ns/iter (+/- 2)
test sys::unix::fd::tests::bench_stack_path_alloc                 ... bench:          15 ns/iter (+/- 1)

For long paths, I couldn't find any measurable difference.


I'd be surprised if I was the first to think of this, so I didn't fully flush out the PR. If this change is desirable, I'll make use of run_with_cstr across all platforms in every fs method (currently just unix open for testing). I also added an impl From<FromBytesWithNulError> which is presumably a no-no (or at least needs to be done in another PR).


Also see nix-rust/nix#1655 with a bunch of discussion where I'm doing something similar.

@rust-highfive
Copy link
Collaborator

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @dtolnay (or someone else) soon.

Please see the contribution instructions for more information.

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Feb 5, 2022
Copy link
Contributor

@bugadani bugadani left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm commenting here for the record instead of requesting a change, because espidf just looks like and talks like a unix target, so including specific changes may not belong in this PR.

cc @ivmarkov who can tell me if I'm wrong and may want to know about this change

// https://docs.rs/compiler_builtins/latest/compiler_builtins/probestack/index.html
//
// Here we chose a typical PATH_MAX minus 2 typical cache lines.
const MAX_STACK_ALLOCATION: usize = 4096 - 2 * 64;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On espidf targets we usually have stack sizes in the order of 4-8k and in most cases this allocation would be an immediate stack overflow.

espidf also uses SPIFFS for its underlying storage which by default has a 32 byte object name length limit (and no folder support at all).

Copy link
Contributor

@Kobzol Kobzol Feb 5, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even though PATH_MAX may usually be 4k, I suppose that most paths will actually be much, much shorter. Since this is an optimization for the fast path, I think that it would be fine to use something like 256 bytes here and it would still apply most of the time.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Kobzol Great point! I whipped up a quick program to analyze my computer's path length stats and got this:

min=17
max=368
mean=125
p50=118
p90=185
p99=244
p999=271
stddev=42
stdvar=1733

256 actually looks super reasonable given those stats, though I feel like we might want to go for 512 just to make sure almost no one ever allocates (since I marked run_with_cstr_allocating as cold and never inline).

Source:

use histogram::Histogram;
use std::env;
use std::fs::{canonicalize, read_dir};
use std::path::Path;

fn main() {
    let args = env::args().collect::<Vec<String>>();

    let mut histogram = Histogram::new();
    if args.len() == 2 {
        log(&mut histogram, canonicalize(&args[1]).unwrap());
    } else {
        log(&mut histogram, canonicalize(".").unwrap());
    }

    println!(
        "min={}\nmax={}\nmean={}\np50={}\np90={}\np99={}\np999={}\nstddev={}\nstdvar={}",
        histogram.minimum().unwrap(),
        histogram.maximum().unwrap(),
        histogram.mean().unwrap(),
        histogram.percentile(50.0).unwrap(),
        histogram.percentile(90.0).unwrap(),
        histogram.percentile(99.0).unwrap(),
        histogram.percentile(99.9).unwrap(),
        histogram.stddev().unwrap(),
        histogram.stdvar().unwrap(),
    )
}

fn log(histogram: &mut Histogram, path: impl AsRef<Path>) {
    for dir in read_dir(path.as_ref()).unwrap() {
        let entry = dir.unwrap();
        histogram
            .increment(entry.path().as_os_str().len() as u64)
            .unwrap();
        if entry.file_type().unwrap().is_dir() {
            log(histogram, entry.path());
        }
    }
}

@hkratz
Copy link
Contributor

hkratz commented Feb 5, 2022

Wouldn't it be better to have a SmallCString type, which works like a SmallVec and implements core::ops::Deref with type Target = CStr? Then we could have cstr_small() returning Result<SmallCString> and just replace cstr() with cstr_small() whereever it makes sense.

@SUPERCILEX
Copy link
Contributor Author

@hkratz Yeah, as mentioned in the PR description this code is nowhere near ready to be merged. I want to make sure this change is desirable before I put in actual effort.

@SUPERCILEX
Copy link
Contributor Author

@dtolnay Can I get some feedback on whether or not this is desired? I just completed similar work in nix: nix-rust/nix#1656.

@SUPERCILEX
Copy link
Contributor Author

Update: I've been analyzing memory allocations in one of my programs that does a lot of I/O and path allocations account for ~15% of all allocations in the program. That's huge for something that should be free!

@SUPERCILEX
Copy link
Contributor Author

r? rust-lang/libs

@rust-highfive rust-highfive assigned m-ou-se and unassigned dtolnay Mar 14, 2022
@bors
Copy link
Contributor

bors commented Apr 15, 2022

☔ The latest upstream changes (presumably #94079) made this pull request unmergeable. Please resolve the merge conflicts.

@joshtriplett
Copy link
Member

The concept of this seems reasonable to me. I agree with the suggestion to reduce the stack allocation to 512 bytes, and I do think the From impl would need to happen in a separate PR that needs an FCP. I also think the run_with_cstr approach may warrant an inline on run_with_cstr, and a check of the generated code to confirm that it doesn't generate an extra function call.

@SUPERCILEX
Copy link
Contributor Author

Awesome! I created #96104 to get that started.

@ivmarkov
Copy link
Contributor

Awesome! I created #96104 to get that started.

Reminder: as discussed earlier, on MCU targets like espidf we need the code path allocating 512 bytes on the stack either completely switched off, or operating with significantly smaller allocation. As in 16 to 32 bytes max. The average stack size on espidf is 3 to 4K.

@SUPERCILEX
Copy link
Contributor Author

@ivmarkov Some random googling says the cache line is 32 bytes on an ESP32, so 32 bytes seems reasonable.

@SUPERCILEX
Copy link
Contributor Author

Ok, I looked into the SmallCStr idea and it actually already exists: https://github.com/rust-lang/rust/blob/master/compiler/rustc_data_structures/src/small_c_str.rs. Unfortunately, that's in the compiler so we'd have to bring over all of SmallVec into std to make things work which doesn't seem like a good idea. Given those issues, I'll continue with the functional approach and figure what the assembly looks like. Should hopefully have time to do this before the end of the week.

@hkratz
Copy link
Contributor

hkratz commented Apr 20, 2022

@SUPERCILEX I have been prototyping a minimal SmallCString implementation without external dependencies. It works fine except for some unnecessary copying in the generated code. I will share the code in a draft PR shortly.

@SUPERCILEX
Copy link
Contributor Author

As long as it's as efficient as single branch on "is bigger than X, then allocate, else use the stack" that works for me. One thing I just thought of: with the SmallCString approach, we're always going to use the same amount of stack space even if we don't need it. That probably doesn't matter, but I think the current approach allows decrementing %rsp only when we plan to use that space and avoid it if we're allocating.

@hkratz
Copy link
Contributor

hkratz commented Apr 20, 2022

The reserved (stack) frame size is fixed for each function in Rust and the stack pointer is decremented accordingly in the beginning of the function (see e.g. Godbolt). So that would be the case for run_with_cstr if it is inlined as well.

@SUPERCILEX
Copy link
Contributor Author

Nevermind + TIL then. 😁 Very cool, thanks for looking into that.

@SUPERCILEX SUPERCILEX changed the title Don't allocate memory in fs path operations Reduce CString allocations in std as much as possible Apr 21, 2022
@SUPERCILEX
Copy link
Contributor Author

r? @joshtriplett

@hkratz Actually, you inspired me to do the SmallCString thing since I realized we don't have to support mutability and can therefore have a much simpler implementation than SmallVec. Let me know if you have feedback on my implementation.

@joshtriplett

  • Why is the tool yelling at me to put stability attributes on SmallCString stuff? It's in a private module, so nothing should escape anyway. Also, did I put it in the right place? I had to make common public to one more level of crates.
  • I went ahead and replaced CString usage for the platforms that were easy, but windows obviously sticks out as being a pain. If someone else wants to do it, feel free to cc me on their PR and I'll be happy to review, but I don't plan on doing anything myself since I don't really care about windows.
  • Who else would want a special stack size? I'm pretty sure I set up the espidf one correctly, but I'm guessing there are other embedded-first architectures that would want something similar.

Check out these sweet-:peach: results!

$ valgrind --tool=dhat target/dr/ftzz g -n 1M /tmp/.tmp$RANDOM

Old:

Total:     437,291 bytes (100%, 2,288.6/Minstr) in 4,275 blocks (100%, 22.37/Minstr), avg size 102.29 bytes, avg lifetime 27,154,908.14 instrs (14.21% of program duration)

New:

Total:     335,808 bytes (100%, 1,761.28/Minstr) in 1,864 blocks (100%, 9.78/Minstr), avg size 180.15 bytes, avg lifetime 61,395,245.76 instrs (32.2% of program duration)

@rustbot rustbot added the T-libs Relevant to the library team, which will review and decide on the PR/issue. label Apr 21, 2022
@SUPERCILEX
Copy link
Contributor Author

It seems like InvalidInput is expected:

Err(e) => assert!(e.kind() == io::ErrorKind::InvalidInput,
Is this something that can change or nah?

@SUPERCILEX
Copy link
Contributor Author

@bors try @rust-timer queue

@bors
Copy link
Contributor

bors commented Apr 21, 2022

@SUPERCILEX: 🔑 Insufficient privileges: not in try users

@rustbot
Copy link
Collaborator

rustbot commented Oct 3, 2022

The Miri subtree was changed

cc @rust-lang/miri

@SUPERCILEX
Copy link
Contributor Author

@joshtriplett take 2? :)

@joshtriplett
Copy link
Member

@bors r+ rollup=never

@bors
Copy link
Contributor

bors commented Oct 9, 2022

📌 Commit 86974b8 has been approved by joshtriplett

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Oct 9, 2022
@bors
Copy link
Contributor

bors commented Oct 9, 2022

⌛ Testing commit 86974b8 with merge 1b22541...

@bors
Copy link
Contributor

bors commented Oct 9, 2022

☀️ Test successful - checks-actions
Approved by: joshtriplett
Pushing 1b22541 to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Oct 9, 2022
@bors bors merged commit 1b22541 into rust-lang:master Oct 9, 2022
@rustbot rustbot added this to the 1.66.0 milestone Oct 9, 2022
@SUPERCILEX
Copy link
Contributor Author

Oh my god, it finally happened!!! 🤩 Thanks everybody!

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (1b22541): comparison URL.

Overall result: ❌ regressions - ACTION NEEDED

Next Steps: If you can justify the regressions found in this perf run, please indicate this with @rustbot label: +perf-regression-triaged along with sufficient written justification. If you cannot justify the regressions please open an issue or create a new PR that fixes the regressions, add a comment linking to the newly created issue or PR, and then add the perf-regression-triaged label to this PR.

@rustbot label: +perf-regression
cc @rust-lang/wg-compiler-performance

Instruction count

This is a highly reliable metric that was used to determine the overall result at the top of this comment.

mean1 range count2
Regressions ❌
(primary)
1.0% [1.0%, 1.0%] 4
Regressions ❌
(secondary)
0.2% [0.2%, 0.2%] 2
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 1.0% [1.0%, 1.0%] 4

Max RSS (memory usage)

Results

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean1 range count2
Regressions ❌
(primary)
0.4% [0.3%, 0.4%] 2
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-3.6% [-8.4%, -1.3%] 6
All ❌✅ (primary) 0.4% [0.3%, 0.4%] 2

Cycles

Results

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean1 range count2
Regressions ❌
(primary)
2.7% [2.7%, 2.7%] 1
Regressions ❌
(secondary)
1.9% [1.6%, 2.2%] 2
Improvements ✅
(primary)
-4.3% [-4.3%, -4.3%] 1
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) -0.8% [-4.3%, 2.7%] 2

Footnotes

  1. the arithmetic mean of the percent change 2 3

  2. number of relevant changes 2 3

@rustbot rustbot added the perf-regression Performance regression. label Oct 9, 2022
@SUPERCILEX
Copy link
Contributor Author

Dang, I'm really not quite sure what to make of these benchmarks. They seem to be flip flopping. My own testing shows a ~4x improvement in instruction count and very minor improvement in real-time in an isolated micro-benchmark.

Test code

    for _ in 0..10_000_000 {
        let z = File::open("Cargo.toml").unwrap();
        std::hint::black_box(&z);
    }

Hyperfine

Benchmark 1: ./old
  Time (mean ± σ):     11.756 s ±  0.226 s    [User: 1.270 s, System: 10.418 s]
  Range (min … max):   11.562 s … 12.268 s    10 runs
 
Benchmark 2: ./new
  Time (mean ± σ):     11.232 s ±  0.153 s    [User: 0.884 s, System: 10.274 s]
  Range (min … max):   11.076 s … 11.634 s    10 runs
 
Summary
  './new' ran
    1.05 ± 0.02 times faster than './old'

Old

==62778== DHAT, a dynamic heap analysis tool
==62778== Copyright (C) 2010-2018, and GNU GPL'd, by Mozilla Foundation
==62778== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==62778== Command: ../target/release/rmz
==62778== 
==62778== 
==62778== Total:     110,002,157 bytes in 10,000,010 blocks
==62778== At t-gmax: 1,736 bytes in 3 blocks
==62778== At t-end:  0 bytes in 0 blocks
==62778== Reads:     90,019,054 bytes
==62778== Writes:    120,011,612 bytes
==62778== 
==62778== To view the resulting profile, open
==62778==   file:///usr/libexec/valgrind/dh_view.html
==62778== in a web browser, click on "Load...", and then select the file
==62778==   /home/asaveau/Desktop/fuc/rmz/dhat.out.62778
==62778== The text at the bottom explains the abbreviations used in the output.
Reading data from 'callgrind.out.65337'...
--------------------------------------------------------------------------------
Profile data file 'callgrind.out.65337' (creator: callgrind-3.18.1)
--------------------------------------------------------------------------------
I1 cache: 32768 B, 64 B, 8-way associative
D1 cache: 32768 B, 64 B, 8-way associative
LL cache: 16777216 B, 64 B, 16-way associative
Timerange: Basic block 0 - 1030069978
Trigger: Program termination
Profiled target:  ../target/dr/rmz (PID 65337, part 1)
Events recorded:  Ir Dr Dw I1mr D1mr D1mw ILmr DLmr DLmw Bc Bcm Bi Bim
Events shown:     Ir Dr Dw I1mr D1mr D1mw ILmr DLmr DLmw Bc Bcm Bi Bim
Event sort order: Ir Dr Dw I1mr D1mr D1mw ILmr DLmr DLmw Bc Bcm Bi Bim
Thresholds:       99 0 0 0 0 0 0 0 0 0 0 0 0
Include dirs:     
User annotated:   
Auto-annotation:  on

--------------------------------------------------------------------------------
Ir                     Dr                     Dw                   I1mr           D1mr           D1mw         ILmr           DLmr           DLmw         Bc                   Bcm                 Bi                  Bim          
--------------------------------------------------------------------------------
4,300,336,369 (100.0%) 1,080,081,361 (100.0%) 730,035,268 (100.0%) 1,679 (100.0%) 2,329 (100.0%) 854 (100.0%) 1,615 (100.0%) 1,807 (100.0%) 793 (100.0%) 740,060,749 (100.0%) 10,004,883 (100.0%) 50,000,898 (100.0%) 383 (100.0%)  PROGRAM TOTALS

--------------------------------------------------------------------------------
Ir                   Dr                   Dw                   I1mr        D1mr         D1mw         ILmr        DLmr         DLmw         Bc                   Bcm                 Bi                  Bim          file:function
--------------------------------------------------------------------------------
640,000,640 (14.88%) 200,000,200 (18.52%) 110,000,110 (15.07%)  7 ( 0.42%)   0            0           7 ( 0.43%)   0            0           90,000,090 (12.16%)          3 ( 0.00%)          .           .           ./malloc/./malloc/malloc.c:_int_free [/usr/lib/x86_64-linux-gnu/libc.so.6]
580,000,000 (13.49%) 100,000,000 ( 9.26%)           0           1 ( 0.06%)   0            0           1 ( 0.06%)   0            0          220,000,000 (29.73%) 10,000,008 (99.95%)          .           .           /rustc/f83e0266cf7aaa4b41505c49a5fd9c2363166522/library/core/src/slice/memchr.rs:<&[u8] as alloc::ffi::c_str::CString::new::SpecNewImpl>::spec_new_impl
430,000,313 (10.00%) 110,000,080 (10.18%)  60,000,027 ( 8.22%)  8 ( 0.48%)   1 ( 0.04%)   0           7 ( 0.43%)   1 ( 0.06%)   0           70,000,067 ( 9.46%)         32 ( 0.00%)          .           .           ./malloc/./malloc/malloc.c:malloc [/usr/lib/x86_64-linux-gnu/libc.so.6]
390,000,000 ( 9.07%) 130,000,000 (12.04%)  20,000,000 ( 2.74%)  5 ( 0.30%)   0            0           5 ( 0.31%)   0            0           90,000,000 (12.16%)         10 ( 0.00%) 10,000,000 (20.00%)  1 ( 0.26%)  /rustc/f83e0266cf7aaa4b41505c49a5fd9c2363166522/library/std/src/sys/unix/fs.rs:std::fs::OpenOptions::_open
340,000,000 ( 7.91%)  70,000,000 ( 6.48%)  40,000,000 ( 5.48%)  3 ( 0.18%)   0            0           3 ( 0.19%)   0            0           50,000,000 ( 6.76%)          .                   .           .           ./io/../sysdeps/unix/sysv/linux/open64.c:open [/usr/lib/x86_64-linux-gnu/libc.so.6]
290,000,000 ( 6.74%)  80,000,000 ( 7.41%) 140,000,000 (19.18%)  3 ( 0.18%)   0            0           3 ( 0.19%)   0            0           20,000,000 ( 2.70%)          .                   .           .           /rustc/f83e0266cf7aaa4b41505c49a5fd9c2363166522/library/alloc/src/ffi/c_str.rs:<&[u8] as alloc::ffi::c_str::CString::new::SpecNewImpl>::spec_new_impl [/home/asaveau/Desktop/fuc/target/dr/rmz]
220,000,198 ( 5.12%)  80,000,072 ( 7.41%)  40,000,036 ( 5.48%)  3 ( 0.18%)   0            0           3 ( 0.19%)   0            0           30,000,027 ( 4.05%)          6 ( 0.00%)          .           .           ./malloc/./malloc/malloc.c:free [/usr/lib/x86_64-linux-gnu/libc.so.6]
180,000,000 ( 4.19%)  70,000,000 ( 6.48%)  60,000,000 ( 8.22%)  2 ( 0.12%)   0            0           2 ( 0.12%)   .            .                    .                   .                   .           .           /rustc/f83e0266cf7aaa4b41505c49a5fd9c2363166522/library/std/src/fs.rs:std::fs::OpenOptions::_open [/home/asaveau/Desktop/fuc/target/dr/rmz]
150,000,015 ( 3.49%)  60,000,006 ( 5.56%)  50,000,005 ( 6.85%)  2 ( 0.12%)   0            0           2 ( 0.12%)   .            .                    .                   .                   .           .           /rustc/f83e0266cf7aaa4b41505c49a5fd9c2363166522/library/alloc/src/ffi/c_str.rs:alloc::ffi::c_str::CString::_from_vec_unchecked [/home/asaveau/Desktop/fuc/target/dr/rmz]
130,000,960 ( 3.02%)  30,000,255 ( 2.78%)  20,000,170 ( 2.74%)  4 ( 0.24%)   1 ( 0.04%)   3 ( 0.35%)  4 ( 0.25%)   1 ( 0.06%)   3 ( 0.38%)  30,000,204 ( 4.05%)         25 ( 0.00%)          .           .           ./string/../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:__memcpy_avx_unaligned_erms [/usr/lib/x86_64-linux-gnu/libc.so.6]
120,000,012 ( 2.79%)  40,000,004 ( 3.70%)  20,000,002 ( 2.74%)  2 ( 0.12%)   0            0           2 ( 0.12%)   0            0           20,000,002 ( 2.70%)          6 ( 0.00%)          .           .           /rustc/f83e0266cf7aaa4b41505c49a5fd9c2363166522/library/alloc/src/vec/mod.rs:alloc::ffi::c_str::CString::_from_vec_unchecked
 90,000,000 ( 2.09%)  20,000,000 ( 1.85%)           0           1 ( 0.06%)   0            0           1 ( 0.06%)   0            0           20,000,000 ( 2.70%)          .                   .           .           ./io/../sysdeps/unix/sysv/linux/close.c:close [/usr/lib/x86_64-linux-gnu/libc.so.6]
 90,000,000 ( 2.09%)  10,000,000 ( 0.93%)           0           2 ( 0.12%)   0            0           2 ( 0.12%)   0            0           10,000,000 ( 1.35%)          .                   .           .           /rustc/f83e0266cf7aaa4b41505c49a5fd9c2363166522/library/std/src/sys/unix/mod.rs:std::fs::OpenOptions::_open
 70,000,014 ( 1.63%)  20,000,004 ( 1.85%)  10,000,002 ( 1.37%)  1 ( 0.06%)   1 ( 0.04%)   0           1 ( 0.06%)   0            0           10,000,002 ( 1.35%)          5 ( 0.00%) 10,000,002 (20.00%)  1 ( 0.26%)  ???:__rust_alloc [/home/asaveau/Desktop/fuc/target/dr/rmz]
 70,000,000 ( 1.63%)           0           20,000,000 ( 2.74%)  .            .            .           .            .            .                    .                   .                   .           .           /rustc/f83e0266cf7aaa4b41505c49a5fd9c2363166522/library/std/src/fs.rs:rmz::main
 70,000,000 ( 1.63%)           0                    0           1 ( 0.06%)   0            0           1 ( 0.06%)   0            0           20,000,000 ( 2.70%)          1 ( 0.00%)          .           .           /rustc/f83e0266cf7aaa4b41505c49a5fd9c2363166522/library/alloc/src/raw_vec.rs:<&[u8] as alloc::ffi::c_str::CString::new::SpecNewImpl>::spec_new_impl
 60,000,000 ( 1.40%)           0           20,000,000 ( 2.74%)  0            0            0           0            0            0           10,000,000 ( 1.35%)          .                   .           .           /rustc/f83e0266cf7aaa4b41505c49a5fd9c2363166522/library/core/src/result.rs:std::fs::OpenOptions::_open
 50,000,000 ( 1.16%)  10,000,000 ( 0.93%)  20,000,000 ( 2.74%)  0            0            0           0            0            0                    0                   0          10,000,000 (20.00%)  1 ( 0.26%)  /rustc/f83e0266cf7aaa4b41505c49a5fd9c2363166522/library/alloc/src/vec/mod.rs:<&[u8] as alloc::ffi::c_str::CString::new::SpecNewImpl>::spec_new_impl
 40,000,000 ( 0.93%)           0           20,000,000 ( 2.74%)  .            .            .           .            .            .                    .                   .                   .           .           /rustc/f83e0266cf7aaa4b41505c49a5fd9c2363166522/library/alloc/src/ffi/c_str.rs:std::fs::OpenOptions::_open
 40,000,000 ( 0.93%)           0           10,000,000 ( 1.37%)  0            0            0           0            0            0           10,000,000 ( 1.35%)          .                   .           .           /rustc/f83e0266cf7aaa4b41505c49a5fd9c2363166522/library/alloc/src/alloc.rs:std::fs::OpenOptions::_open
 30,000,027 ( 0.70%)           0                    0           0            0            0           0            0            0           10,000,009 ( 1.35%)          7 ( 0.00%)          .           .           ./malloc/./malloc/arena.c:free
 30,000,022 ( 0.70%)  10,000,008 ( 0.93%)  20,000,006 ( 2.74%)  1 ( 0.06%)   0            0           1 ( 0.06%)   .            .                    .                   .                   .           .           src/main.rs:rmz::main [/home/asaveau/Desktop/fuc/target/dr/rmz]
 30,000,003 ( 0.70%)  10,000,001 ( 0.93%)           0           0            0            0           0            0            0           10,000,001 ( 1.35%)          3 ( 0.00%)          .           .           /rustc/f83e0266cf7aaa4b41505c49a5fd9c2363166522/library/alloc/src/raw_vec.rs:alloc::ffi::c_str::CString::_from_vec_unchecked
 30,000,000 ( 0.70%)  20,000,000 ( 1.85%)           0           1 ( 0.06%)   0            0           1 ( 0.06%)   0            0           10,000,000 ( 1.35%)          .                   .           .           /rustc/f83e0266cf7aaa4b41505c49a5fd9c2363166522/library/core/src/result.rs:rmz::main
 30,000,000 ( 0.70%)           0           30,000,000 ( 4.11%)  1 ( 0.06%)   0            0           1 ( 0.06%)   .            .                    .                   .                   .           .           /rustc/f83e0266cf7aaa4b41505c49a5fd9c2363166522/library/std/src/sys/unix/fs.rs:rmz::main
 30,000,000 ( 0.70%)           0           10,000,000 ( 1.37%)  .            .            .           .            .            .                    .                   .                   .           .           /rustc/f83e0266cf7aaa4b41505c49a5fd9c2363166522/library/alloc/src/alloc.rs:<&[u8] as alloc::ffi::c_str::CString::new::SpecNewImpl>::spec_new_impl
 20,000,000 ( 0.47%)           .                    .           .            .            .           .            .            .                    .                   .                   .           .           /rustc/f83e0266cf7aaa4b41505c49a5fd9c2363166522/library/core/src/num/uint_macros.rs:<&[u8] as alloc::ffi::c_str::CString::new::SpecNewImpl>::spec_new_impl
 10,000,002 ( 0.23%)  10,000,002 ( 0.93%)           0           1 ( 0.06%)   0            0           1 ( 0.06%)   0            0                    0                   0          10,000,002 (20.00%)  1 ( 0.26%)  ???:__rust_dealloc [/home/asaveau/Desktop/fuc/target/dr/rmz]

--------------------------------------------------------------------------------
-- Auto-annotated source: src/main.rs
--------------------------------------------------------------------------------
Ir                  Dr                  Dw                  I1mr       D1mr       D1mw       ILmr       DLmr DLmw Bc Bcm Bi Bim 

-- line 27 ----------------------------------------
         .                   .                   .          .          .          .          .          .          .          .          .          .          .               #[clap(flatten)]
         .                   .                   .          .          .          .          .          .          .          .          .          .          .               verbose: Verbosity,
         .                   .                   .          .          .          .          .          .          .          .          .          .          .               #[arg(short, long, short_alias = '?', global = true)]
         .                   .                   .          .          .          .          .          .          .          .          .          .          .               #[arg(action = ArgAction::Help, help = "Print help information (use `--help` for more detail)")]
         .                   .                   .          .          .          .          .          .          .          .          .          .          .               #[arg(long_help = "Print help information (use `-h` for a summary)")]
         .                   .                   .          .          .          .          .          .          .          .          .          .          .               help: Option<bool>,
         .                   .                   .          .          .          .          .          .          .          .          .          .          .           }
         .                   .                   .          .          .          .          .          .          .          .          .          .          .           
        14 ( 0.00%)          1 ( 0.00%)          6 ( 0.00%) 1 ( 0.06%) 0          0          1 ( 0.06%) .          .          .          .          .          .           fn main() {
         .                   .                   .          .          .          .          .          .          .          .          .          .          .               // let args = Rmz::parse();
         .                   .                   .          .          .          .          .          .          .          .          .          .          .               //
         .                   .                   .          .          .          .          .          .          .          .          .          .          .               // RemoveOp::builder()
         .                   .                   .          .          .          .          .          .          .          .          .          .          .               //     .files(args.files.iter().map(AsRef::as_ref))
         .                   .                   .          .          .          .          .          .          .          .          .          .          .               //     .build()
         .                   .                   .          .          .          .          .          .          .          .          .          .          .               //     .run()
         .                   .                   .          .          .          .          .          .          .          .          .          .          .               //     .unwrap();
         .                   .                   .          .          .          .          .          .          .          .          .          .          .           
         .                   .                   .          .          .          .          .          .          .          .          .          .          .               for _ in 0..10_000_000 {
10,000,000 ( 0.23%)          0          10,000,000 ( 1.37%) .          .          .          .          .          .          .          .          .          .                   let z = File::open("Cargo.toml").unwrap();
10,000,000 ( 0.23%)          0          10,000,000 ( 1.37%) .          .          .          .          .          .          .          .          .          .                   std::hint::black_box(&z);
10,000,000 ( 0.23%) 10,000,000 ( 0.93%)          .          .          .          .          .          .          .          .          .          .          .               }
         8 ( 0.00%)          7 ( 0.00%)          .          .          .          .          .          .          .          .          .          .          .           }
         .                   .                   .          .          .          .          .          .          .          .          .          .          .           
         .                   .                   .          .          .          .          .          .          .          .          .          .          .           #[cfg(test)]
         .                   .                   .          .          .          .          .          .          .          .          .          .          .           mod cli_tests {
         .                   .                   .          .          .          .          .          .          .          .          .          .          .               use std::io::Write;
         .                   .                   .          .          .          .          .          .          .          .          .          .          .           
         .                   .                   .          .          .          .          .          .          .          .          .          .          .               use clap::{Command, CommandFactory};
         .                   .                   .          .          .          .          .          .          .          .          .          .          .               use goldenfile::Mint;
         .                   .                   .          .          .          .          .          .          .          .          .          .          .           
-- line 56 ----------------------------------------

--------------------------------------------------------------------------------
The following files chosen for auto-annotation could not be found:
--------------------------------------------------------------------------------
  ./io/../sysdeps/unix/sysv/linux/close.c
  ./io/../sysdeps/unix/sysv/linux/open64.c
  ./malloc/./malloc/arena.c
  ./malloc/./malloc/malloc.c
  ./string/../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S
  /rustc/f83e0266cf7aaa4b41505c49a5fd9c2363166522/library/alloc/src/alloc.rs
  /rustc/f83e0266cf7aaa4b41505c49a5fd9c2363166522/library/alloc/src/ffi/c_str.rs
  /rustc/f83e0266cf7aaa4b41505c49a5fd9c2363166522/library/alloc/src/raw_vec.rs
  /rustc/f83e0266cf7aaa4b41505c49a5fd9c2363166522/library/alloc/src/vec/mod.rs
  /rustc/f83e0266cf7aaa4b41505c49a5fd9c2363166522/library/core/src/num/uint_macros.rs
  /rustc/f83e0266cf7aaa4b41505c49a5fd9c2363166522/library/core/src/result.rs
  /rustc/f83e0266cf7aaa4b41505c49a5fd9c2363166522/library/core/src/slice/memchr.rs
  /rustc/f83e0266cf7aaa4b41505c49a5fd9c2363166522/library/std/src/fs.rs
  /rustc/f83e0266cf7aaa4b41505c49a5fd9c2363166522/library/std/src/sys/unix/fs.rs
  /rustc/f83e0266cf7aaa4b41505c49a5fd9c2363166522/library/std/src/sys/unix/mod.rs

--------------------------------------------------------------------------------
Ir                  Dr                  Dw                  I1mr       D1mr       D1mw       ILmr       DLmr DLmw Bc Bcm Bi Bim 
--------------------------------------------------------------------------------
30,000,022 ( 0.70%) 10,000,008 ( 0.93%) 20,000,006 ( 2.74%) 1 ( 0.06%) 0          0          1 ( 0.06%) .          .          .          .          .          .           events annotated

New

==62459== DHAT, a dynamic heap analysis tool
==62459== Copyright (C) 2010-2018, and GNU GPL'd, by Mozilla Foundation
==62459== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==62459== Command: ../target/release/rmz
==62459== 
==62459== 
==62459== Total:     2,157 bytes in 10 blocks
==62459== At t-gmax: 1,736 bytes in 3 blocks
==62459== At t-end:  0 bytes in 0 blocks
==62459== Reads:     19,054 bytes
==62459== Writes:    11,612 bytes
==62459== 
==62459== To view the resulting profile, open
==62459==   file:///usr/libexec/valgrind/dh_view.html
==62459== in a web browser, click on "Load...", and then select the file
==62459==   /home/asaveau/Desktop/fuc/rmz/dhat.out.62459
==62459== The text at the bottom explains the abbreviations used in the output.
Reading data from 'callgrind.out.64019'...
--------------------------------------------------------------------------------
Profile data file 'callgrind.out.64019' (creator: callgrind-3.18.1)
--------------------------------------------------------------------------------
I1 cache: 32768 B, 64 B, 8-way associative
D1 cache: 32768 B, 64 B, 8-way associative
LL cache: 16777216 B, 64 B, 16-way associative
Timerange: Basic block 0 - 320068730
Trigger: Program termination
Profiled target:  ../target/dr/rmz (PID 64019, part 1)
Events recorded:  Ir Dr Dw I1mr D1mr D1mw ILmr DLmr DLmw Bc Bcm Bi Bim
Events shown:     Ir Dr Dw I1mr D1mr D1mw ILmr DLmr DLmw Bc Bcm Bi Bim
Event sort order: Ir Dr Dw I1mr D1mr D1mw ILmr DLmr DLmw Bc Bcm Bi Bim
Thresholds:       99 0 0 0 0 0 0 0 0 0 0 0 0
Include dirs:     
User annotated:   
Auto-annotation:  on

--------------------------------------------------------------------------------
Ir                     Dr                   Dw                   I1mr           D1mr           D1mw         ILmr           DLmr           DLmw         Bc                   Bcm            Bi                  Bim          
--------------------------------------------------------------------------------
1,360,331,309 (100.0%) 300,080,409 (100.0%) 240,034,628 (100.0%) 1,678 (100.0%) 2,354 (100.0%) 865 (100.0%) 1,617 (100.0%) 1,828 (100.0%) 804 (100.0%) 220,059,708 (100.0%) 4,868 (100.0%) 20,000,846 (100.0%) 355 (100.0%)  PROGRAM TOTALS

--------------------------------------------------------------------------------
Ir                   Dr                   Dw                  I1mr        D1mr         D1mw         ILmr        DLmr         DLmw         Bc                  Bcm          Bi                  Bim          file:function
--------------------------------------------------------------------------------
600,000,000 (44.11%) 170,000,000 (56.65%) 90,000,000 (37.49%)  7 ( 0.42%)   0            0           7 ( 0.43%)   0            0          90,000,000 (40.90%)  11 ( 0.23%) 10,000,000 (50.00%)  1 ( 0.28%)  ???:std::sys::unix::fs::File::open_c [/home/asaveau/Desktop/fuc/target/dr/rmz]
340,000,000 (24.99%)  70,000,000 (23.33%) 40,000,000 (16.66%)  3 ( 0.18%)   0            0           3 ( 0.19%)   0            0          50,000,000 (22.72%)   .                   .           .           ./io/../sysdeps/unix/sysv/linux/open64.c:open [/usr/lib/x86_64-linux-gnu/libc.so.6]
270,000,000 (19.85%)  30,000,000 (10.00%) 80,000,000 (33.33%)  2 ( 0.12%)   0            0           2 ( 0.12%)   0            0          50,000,000 (22.72%)   .                   .           .           /home/asaveau/Desktop/rust/library/std/src/fs.rs:rmz::main
 90,000,000 ( 6.62%)  20,000,000 ( 6.66%)          0           1 ( 0.06%)   0            0           1 ( 0.06%)   0            0          20,000,000 ( 9.09%)   .                   .           .           ./io/../sysdeps/unix/sysv/linux/close.c:close [/usr/lib/x86_64-linux-gnu/libc.so.6]
 30,000,026 ( 2.21%)  10,000,008 ( 3.33%) 20,000,006 ( 8.33%)  3 ( 0.18%)   0            0           3 ( 0.19%)   .            .                   .            .                   .           .           src/main.rs:rmz::main [/home/asaveau/Desktop/fuc/target/dr/rmz]
 10,000,000 ( 0.74%)           0          10,000,000 ( 4.17%)  0            0            0           0            0            0                   0            0          10,000,000 (50.00%)  1 ( 0.28%)  /home/asaveau/Desktop/rust/library/std/src/os/fd/owned.rs:rmz::main
 10,000,000 ( 0.74%)           0                   0           0            0            0           0            0            0          10,000,000 ( 4.54%)   3 ( 0.06%)          .           .           /home/asaveau/Desktop/rust/library/core/src/iter/range.rs:rmz::main

--------------------------------------------------------------------------------
-- Auto-annotated source: src/main.rs
--------------------------------------------------------------------------------
Ir                  Dr                  Dw                  I1mr       D1mr       D1mw       ILmr       DLmr DLmw Bc Bcm Bi Bim 

-- line 27 ----------------------------------------
         .                   .                   .          .          .          .          .          .          .          .          .          .          .               #[clap(flatten)]
         .                   .                   .          .          .          .          .          .          .          .          .          .          .               verbose: Verbosity,
         .                   .                   .          .          .          .          .          .          .          .          .          .          .               #[arg(short, long, short_alias = '?', global = true)]
         .                   .                   .          .          .          .          .          .          .          .          .          .          .               #[arg(action = ArgAction::Help, help = "Print help information (use `--help` for more detail)")]
         .                   .                   .          .          .          .          .          .          .          .          .          .          .               #[arg(long_help = "Print help information (use `-h` for a summary)")]
         .                   .                   .          .          .          .          .          .          .          .          .          .          .               help: Option<bool>,
         .                   .                   .          .          .          .          .          .          .          .          .          .          .           }
         .                   .                   .          .          .          .          .          .          .          .          .          .          .           
        18 ( 0.00%)          1 ( 0.00%)          6 ( 0.00%) 2 ( 0.12%) 0          0          2 ( 0.12%) .          .          .          .          .          .           fn main() {
         .                   .                   .          .          .          .          .          .          .          .          .          .          .               // let args = Rmz::parse();
         .                   .                   .          .          .          .          .          .          .          .          .          .          .               //
         .                   .                   .          .          .          .          .          .          .          .          .          .          .               // RemoveOp::builder()
         .                   .                   .          .          .          .          .          .          .          .          .          .          .               //     .files(args.files.iter().map(AsRef::as_ref))
         .                   .                   .          .          .          .          .          .          .          .          .          .          .               //     .build()
         .                   .                   .          .          .          .          .          .          .          .          .          .          .               //     .run()
         .                   .                   .          .          .          .          .          .          .          .          .          .          .               //     .unwrap();
         .                   .                   .          .          .          .          .          .          .          .          .          .          .           
         .                   .                   .          .          .          .          .          .          .          .          .          .          .               for _ in 0..10_000_000 {
10,000,000 ( 0.74%)          0          10,000,000 ( 4.17%) .          .          .          .          .          .          .          .          .          .                   let z = File::open("Cargo.toml").unwrap();
10,000,000 ( 0.74%)          0          10,000,000 ( 4.17%) .          .          .          .          .          .          .          .          .          .                   std::hint::black_box(&z);
10,000,000 ( 0.74%) 10,000,000 ( 3.33%)          .          .          .          .          .          .          .          .          .          .          .               }
         8 ( 0.00%)          7 ( 0.00%)          0          1 ( 0.06%) 0          0          1 ( 0.06%) .          .          .          .          .          .           }
         .                   .                   .          .          .          .          .          .          .          .          .          .          .           
         .                   .                   .          .          .          .          .          .          .          .          .          .          .           #[cfg(test)]
         .                   .                   .          .          .          .          .          .          .          .          .          .          .           mod cli_tests {
         .                   .                   .          .          .          .          .          .          .          .          .          .          .               use std::io::Write;
         .                   .                   .          .          .          .          .          .          .          .          .          .          .           
         .                   .                   .          .          .          .          .          .          .          .          .          .          .               use clap::{Command, CommandFactory};
         .                   .                   .          .          .          .          .          .          .          .          .          .          .               use goldenfile::Mint;
         .                   .                   .          .          .          .          .          .          .          .          .          .          .           
-- line 56 ----------------------------------------

--------------------------------------------------------------------------------
-- Auto-annotated source: /home/asaveau/Desktop/rust/library/core/src/iter/range.rs
--------------------------------------------------------------------------------
Ir                  Dr         Dw         I1mr       D1mr       D1mw       ILmr       DLmr       DLmw       Bc                  Bcm        Bi Bim 

-- line 613 ----------------------------------------
         .          .          .          .          .          .          .          .          .                   .          .          .          .           
         .          .          .          .          .          .          .          .          .                   .          .          .          .                   if taken < n { Err(taken) } else { Ok(()) }
         .          .          .          .          .          .          .          .          .                   .          .          .          .               }
         .          .          .          .          .          .          .          .          .                   .          .          .          .           }
         .          .          .          .          .          .          .          .          .                   .          .          .          .           
         .          .          .          .          .          .          .          .          .                   .          .          .          .           impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> {
         .          .          .          .          .          .          .          .          .                   .          .          .          .               #[inline]
         .          .          .          .          .          .          .          .          .                   .          .          .          .               fn spec_next(&mut self) -> Option<T> {
10,000,000 ( 0.74%) 0          0          0          0          0          0          0          0          10,000,000 ( 4.54%) 3 ( 0.06%) .          .                   if self.start < self.end {
         .          .          .          .          .          .          .          .          .                   .          .          .          .                       // SAFETY: just checked precondition
         .          .          .          .          .          .          .          .          .                   .          .          .          .                       let n = unsafe { Step::forward_unchecked(self.start.clone(), 1) };
         .          .          .          .          .          .          .          .          .                   .          .          .          .                       Some(mem::replace(&mut self.start, n))
         .          .          .          .          .          .          .          .          .                   .          .          .          .                   } else {
         .          .          .          .          .          .          .          .          .                   .          .          .          .                       None
         .          .          .          .          .          .          .          .          .                   .          .          .          .                   }
         .          .          .          .          .          .          .          .          .                   .          .          .          .               }
         .          .          .          .          .          .          .          .          .                   .          .          .          .           
-- line 629 ----------------------------------------

--------------------------------------------------------------------------------
-- Auto-annotated source: /home/asaveau/Desktop/rust/library/std/src/fs.rs
--------------------------------------------------------------------------------
Ir                   Dr                  Dw                  I1mr       D1mr       D1mw       ILmr       DLmr       DLmw       Bc                  Bcm Bi Bim 

-- line 344 ----------------------------------------
          .                   .                   .          .          .          .          .          .          .                   .          .          .          .               ///
          .                   .                   .          .          .          .          .          .          .                   .          .          .          .               /// fn main() -> std::io::Result<()> {
          .                   .                   .          .          .          .          .          .          .                   .          .          .          .               ///     let mut f = File::open("foo.txt")?;
          .                   .                   .          .          .          .          .          .          .                   .          .          .          .               ///     Ok(())
          .                   .                   .          .          .          .          .          .          .                   .          .          .          .               /// }
          .                   .                   .          .          .          .          .          .          .                   .          .          .          .               /// ```
          .                   .                   .          .          .          .          .          .          .                   .          .          .          .               #[stable(feature = "rust1", since = "1.0.0")]
          .                   .                   .          .          .          .          .          .          .                   .          .          .          .               pub fn open<P: AsRef<Path>>(path: P) -> io::Result<File> {
 50,000,000 ( 3.68%)          0          40,000,000 (16.66%) 1 ( 0.06%) 0          0          1 ( 0.06%) .          .                   .          .          .          .                   OpenOptions::new().read(true).open(path.as_ref())
          .                   .                   .          .          .          .          .          .          .                   .          .          .          .               }
          .                   .                   .          .          .          .          .          .          .                   .          .          .          .           
          .                   .                   .          .          .          .          .          .          .                   .          .          .          .               /// Opens a file in write-only mode.
          .                   .                   .          .          .          .          .          .          .                   .          .          .          .               ///
          .                   .                   .          .          .          .          .          .          .                   .          .          .          .               /// This function will create a file if it does not exist,
          .                   .                   .          .          .          .          .          .          .                   .          .          .          .               /// and will truncate it if it does.
          .                   .                   .          .          .          .          .          .          .                   .          .          .          .               ///
          .                   .                   .          .          .          .          .          .          .                   .          .          .          .               /// Depending on the platform, this function may fail if the
-- line 360 ----------------------------------------
-- line 1048 ----------------------------------------
          .                   .                   .          .          .          .          .          .          .                   .          .          .          .               /// ```
          .                   .                   .          .          .          .          .          .          .                   .          .          .          .               ///
          .                   .                   .          .          .          .          .          .          .                   .          .          .          .               /// [`AlreadyExists`]: io::ErrorKind::AlreadyExists
          .                   .                   .          .          .          .          .          .          .                   .          .          .          .               /// [`InvalidInput`]: io::ErrorKind::InvalidInput
          .                   .                   .          .          .          .          .          .          .                   .          .          .          .               /// [`NotFound`]: io::ErrorKind::NotFound
          .                   .                   .          .          .          .          .          .          .                   .          .          .          .               /// [`PermissionDenied`]: io::ErrorKind::PermissionDenied
          .                   .                   .          .          .          .          .          .          .                   .          .          .          .               #[stable(feature = "rust1", since = "1.0.0")]
          .                   .                   .          .          .          .          .          .          .                   .          .          .          .               pub fn open<P: AsRef<Path>>(&self, path: P) -> io::Result<File> {
220,000,000 (16.17%) 30,000,000 (10.00%) 40,000,000 (16.66%) 1 ( 0.06%) 0          0          1 ( 0.06%) 0          0          50,000,000 (22.72%) .          .          .                   self._open(path.as_ref())
940,000,000 (69.10%) 240,000,000 (79.98%) 130,000,000 (54.16%) 10 ( 0.60%) 0          0          10 ( 0.62%) 0          0          140,000,000 (63.62%) 11 ( 0.23%) 10,000,000 (50.00%) 1 ( 0.28%)  => ???:std::sys::unix::fs::File::open_c (10,000,000x)
          .                   .                   .          .          .          .          .          .          .                   .          .          .          .               }
          .                   .                   .          .          .          .          .          .          .                   .          .          .          .           
          .                   .                   .          .          .          .          .          .          .                   .          .          .          .               fn _open(&self, path: &Path) -> io::Result<File> {
          .                   .                   .          .          .          .          .          .          .                   .          .          .          .                   fs_imp::File::open(path, &self.0).map(|inner| File { inner })
          .                   .                   .          .          .          .          .          .          .                   .          .          .          .               }
          .                   .                   .          .          .          .          .          .          .                   .          .          .          .           }
          .                   .                   .          .          .          .          .          .          .                   .          .          .          .           
          .                   .                   .          .          .          .          .          .          .                   .          .          .          .           impl AsInner<fs_imp::OpenOptions> for OpenOptions {
-- line 1064 ----------------------------------------

--------------------------------------------------------------------------------
-- Auto-annotated source: /home/asaveau/Desktop/rust/library/std/src/os/fd/owned.rs
--------------------------------------------------------------------------------
Ir                  Dr         Dw                  I1mr       D1mr       D1mw       ILmr       DLmr       DLmw       Bc         Bcm        Bi                  Bim        

-- line 168 ----------------------------------------
         .          .                   .          .          .          .          .          .          .          .          .                   .          .               #[inline]
         .          .                   .          .          .          .          .          .          .          .          .                   .          .               fn drop(&mut self) {
         .          .                   .          .          .          .          .          .          .          .          .                   .          .                   unsafe {
         .          .                   .          .          .          .          .          .          .          .          .                   .          .                       // Note that errors are ignored when closing a file descriptor. The
         .          .                   .          .          .          .          .          .          .          .          .                   .          .                       // reason for this is that if an error occurs we don't actually know if
         .          .                   .          .          .          .          .          .          .          .          .                   .          .                       // the file descriptor was closed or not, and if we retried (for
         .          .                   .          .          .          .          .          .          .          .          .                   .          .                       // something like EINTR), we might close another valid file descriptor
         .          .                   .          .          .          .          .          .          .          .          .                   .          .                       // opened after we closed ours.
10,000,000 ( 0.74%) 0          10,000,000 ( 4.17%) 0          0          0          0          0          0          0          0          10,000,000 (50.00%) 1 ( 0.28%)              let _ = libc::close(self.fd);
90,000,000 ( 6.62%) 20,000,000 ( 6.66%)          0          1 ( 0.06%) 0          0          1 ( 0.06%) 0          0          20,000,000 ( 9.09%) .                   .          .           => ./io/../sysdeps/unix/sysv/linux/close.c:close (10,000,000x)
         .          .                   .          .          .          .          .          .          .          .          .                   .          .                   }
         .          .                   .          .          .          .          .          .          .          .          .                   .          .               }
         .          .                   .          .          .          .          .          .          .          .          .                   .          .           }
         .          .                   .          .          .          .          .          .          .          .          .                   .          .           
         .          .                   .          .          .          .          .          .          .          .          .                   .          .           #[stable(feature = "io_safety", since = "1.63.0")]
         .          .                   .          .          .          .          .          .          .          .          .                   .          .           impl fmt::Debug for BorrowedFd<'_> {
         .          .                   .          .          .          .          .          .          .          .          .                   .          .               fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         .          .                   .          .          .          .          .          .          .          .          .                   .          .                   f.debug_struct("BorrowedFd").field("fd", &self.fd).finish()
-- line 184 ----------------------------------------

--------------------------------------------------------------------------------
The following files chosen for auto-annotation could not be found:
--------------------------------------------------------------------------------
  ./io/../sysdeps/unix/sysv/linux/close.c
  ./io/../sysdeps/unix/sysv/linux/open64.c

--------------------------------------------------------------------------------
Ir                   Dr                  Dw                   I1mr       D1mr       D1mw       ILmr       DLmr       DLmw       Bc                  Bcm        Bi                  Bim        
--------------------------------------------------------------------------------
320,000,026 (23.52%) 40,000,008 (13.33%) 110,000,006 (45.83%) 5 ( 0.30%) 0          0          5 ( 0.31%) 0          0          60,000,000 (27.27%) 3 ( 0.06%) 10,000,000 (50.00%) 1 ( 0.28%)  events annotated

@Kobzol
Copy link
Contributor

Kobzol commented Oct 9, 2022

We don't have runtime benchmarks yet, these are compile time benchmarks. The results look mostly neutral.

@SUPERCILEX
Copy link
Contributor Author

Whew, ok.

@rylev
Copy link
Member

rylev commented Oct 11, 2022

The hello-world opt benchmarks are dominated by link time. It makes sense that a change to an FFI type CString could have an impact on these. I don't think there's a need though to really do anything about it.

@rustbot labels: +perf-regression-triaged

@rustbot rustbot added the perf-regression-triaged The performance regression has been triaged. label Oct 11, 2022
Aaron1011 pushed a commit to Aaron1011/rust that referenced this pull request Jan 6, 2023
Reduce CString allocations in std as much as possible

Currently, every operation involving paths in `fs` allocates memory to hold the path before sending it through the syscall. This PR instead uses a stack allocation (chosen size is somewhat arbitrary) when the path is short before falling back to heap allocations for long paths.

Benchmarks show that the stack allocation is ~2x faster for short paths:

```
test sys::unix::fd::tests::bench_heap_path_alloc                  ... bench:          34 ns/iter (+/- 2)
test sys::unix::fd::tests::bench_stack_path_alloc                 ... bench:          15 ns/iter (+/- 1)
```

For long paths, I couldn't find any measurable difference.

---

I'd be surprised if I was the first to think of this, so I didn't fully flush out the PR. If this change is desirable, I'll make use of `run_with_cstr` across all platforms in every fs method (currently just unix open for testing). I also added an `impl From<FromBytesWithNulError>` which is presumably a no-no (or at least needs to be done in another PR).

---

Also see nix-rust/nix#1655 with a bunch of discussion where I'm doing something similar.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged-by-bors This PR was explicitly merged by bors. perf-regression Performance regression. perf-regression-triaged The performance regression has been triaged. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-infra Relevant to the infrastructure team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.