-
Notifications
You must be signed in to change notification settings - Fork 13k
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
io::copy does not use copy_file_range consistently #114341
Comments
FWIW I'm interested in proposing a code change for this if there's agreement given this behavior is non-ideal, or at least, unexpected. Possibly adding a |
Yes, this should be fine. Adding a
You shouldn't be doing that since it would prematurely close stdout once it's dropped. Acquire a |
In this example, wouldn't that be when The reason I did it like that, for context, is that I found the implicit
I agree, that didn't make much sense after some consideration - passing the I'll work on a PR for this. |
Using |
AH yes, of course - originally I was working with arbitrary streaming data (via pipes) so I missed this nuance when I got to implementing Would you say it's sufficient to just lock these "at the top" like I'm doing here so you can ultimately choose whether you pass the |
let input = io::stdin().lock();
let output: StdoutLock = io::stdout().lock();
let buffered_out = BufWriter::new(output);
// ...
io::copy(&mut input, &mut buffered_out) no |
Aha! I think I narrowed down some more of confusion here - indeed, when using
It's still line buffering when it falls back completely to |
I see. urandom is a char device, we don't have special path for that in I don't think this is worth special-casing in the standard library for the moment. Instead #60673 needs to be solved. As a workaround you can do this: let locked = stdout().locked();
let writer = BufWriter::new(File::from(locked.as_fd().try_clone_to_owned().unwrap())); |
This is super helpful - thanks! I'm glad to remove anything For posterity here is working code which also sets the buffer size > than the default (
This wreaks of premature optimization but ultimately I was just shooting for 1:1 low-level behavior/functionality with I'd be happy to see the Sorry for derailing the original issue discussion (continued in the PR #114373) but this has been very enlightening. |
This is for rust-lang#114341 The `meta.len() > 0` condition here is intended for inputs only, ie. when input is in the `/proc` filesystem as documented. That inaccurately included empty output files which are then shunted to the sendfile() routine leading to higher than nescessary IO util in some cases, specifically with CoW filesystems like btrfs. Further, `NoneObtained` is not relevant in this context, so remove it. Simply, determine what is input or output given the passed enum Unit.
unix/kernel_copy.rs: copy_file_range_candidate allows empty output files This is for rust-lang#114341 The `meta.len() > 0` condition here is intended for inputs only, ie. when input is in the `/proc` filesystem as documented. That inaccurately included empty output files which are then shunted to the sendfile() routine leading to higher than nescessary IO util in some cases, specifically with CoW filesystems like btrfs. Simply, determine what is input or output given the passed boolean.
This is for rust-lang/rust#114341 The `meta.len() > 0` condition here is intended for inputs only, ie. when input is in the `/proc` filesystem as documented. That inaccurately included empty output files which are then shunted to the sendfile() routine leading to higher than nescessary IO util in some cases, specifically with CoW filesystems like btrfs. Further, `NoneObtained` is not relevant in this context, so remove it. Simply, determine what is input or output given the passed enum Unit.
unix/kernel_copy.rs: copy_file_range_candidate allows empty output files This is for rust-lang/rust#114341 The `meta.len() > 0` condition here is intended for inputs only, ie. when input is in the `/proc` filesystem as documented. That inaccurately included empty output files which are then shunted to the sendfile() routine leading to higher than nescessary IO util in some cases, specifically with CoW filesystems like btrfs. Simply, determine what is input or output given the passed boolean.
I tried this code:
test.rs
:Testing:
I expected to see this happen:
io::copy
initially detects thatcopy_file_range
is available for the copy from regular file to regular file (truncated by the shell redirection)Instead, this happened:
io::copy
initially usessendfile
on the first iteration and then determinescopy_file_range
is a candidateie. when
stdout
redirected to a regular file which is nowmeta.len() > 0
The
meta.len() > 0
logic does not make sense for outputs AFAICT - only inputs (ie./proc
filesystems, as documented)rust/library/std/src/sys/unix/kernel_copy.rs
Line 121 in 4896daa
copy_file_range
can populate the initially empty (regular) output file without issue, that's how coreutilscat
works today.Meta
rustc --version --verbose
:The text was updated successfully, but these errors were encountered: