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

Tracking issue for vectored IO support #58452

Closed
sfackler opened this issue Feb 14, 2019 · 35 comments · Fixed by #60334
Closed

Tracking issue for vectored IO support #58452

sfackler opened this issue Feb 14, 2019 · 35 comments · Fixed by #60334
Labels
B-unstable Blocker: Implemented in the nightly compiler and unstable. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. finished-final-comment-period The final comment period is finished for this PR / Issue. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@sfackler
Copy link
Member

This covers Read::read_vectored, Write::write_vectored, IoVec, and IoVecMut.

@sfackler sfackler added T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. B-unstable Blocker: Implemented in the nightly compiler and unstable. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. labels Feb 14, 2019
@abonander
Copy link
Contributor

@sfackler is this for an open PR or pending RFC? I can't find anything relevant.

@jonas-schievink
Copy link
Contributor

Introduced in #58357

@withoutboats
Copy link
Contributor

I'd like to at least investigate the DST solution before we stabilize to see what would be the blockers. It would be a pleasant outcome to have these types written &'a IoVec and &'a mut IoVec instead of having the two lifetime-parameterized types.

@withoutboats
Copy link
Contributor

Looked into what making this into a DST would entail; it looks like what these need is some way to specify the metadata type, because on some platforms the metadata is not the same ABI as a usize (specifically on 64-bit windows it seems to be a u32).

@sfackler
Copy link
Member Author

You also need control over the ordering - the length field comes before the pointer in a WSABUF.

@withoutboats
Copy link
Contributor

Oh jeez, I'm not sure that we can accomplish having a T in which the first word of &T is not the address.

@sfackler
Copy link
Member Author

Yeah. The iovec crate hacked around this by having the DST be a slice where the length was secretly the pointer and the pointer was secretly the length, but it's then unsound to have an empty iovec. It just barely happens to work. If we targeted a slightly weirder platform with e.g. a 32 byte length and 4-byte aligned pointers we'd be SOL.

@withoutboats
Copy link
Contributor

I mean isn't that hack broken as soon as someone writes as *const _ and they get the first word? If we had language support we'd fix that, but I suspect we will discover that people are relying on the first word being the address in ways we can't automatically patch up.

@jethrogb
Copy link
Contributor

jethrogb commented Mar 8, 2019

There is a test in tcp:

let a = [];
let b = [10];
let c = [11, 12];
t!(s1.write_vectored(&[IoVec::new(&a), IoVec::new(&b), IoVec::new(&c)]));

let mut buf = [0; 4];
let len = t!(s2.read(&mut buf));
// some implementations don't support writev, so we may only write the first buffer
if len == 1 {
    assert_eq!(buf, [10, 0, 0, 0]);
} else {
    assert_eq!(len, 3);
    assert_eq!(buf, [10, 11, 12, 0]);
}

However, the first buffer is the empty buffer, so some platforms don't write anything at all! From src/libstd/sys/sgx/net.rs:

    pub fn write_vectored(&self, buf: &[IoVec<'_>]) -> io::Result<usize> {
        let buf = match buf.get(0) {
            Some(buf) => buf,
            None => return Ok(0),
        };
        self.write(buf)
    }

The documentation for write_vectored leaves something to be desired:

Data is copied to from each buffer in order, with the final buffer read from possibly being only partially consumed. This method must behave as a call to write with the buffers concatenated would.

I'm not exactly sure what the expected behavior here is.

@sfackler
Copy link
Member Author

sfackler commented Mar 8, 2019

Oh, oops, I forgot to fix the SGX implementation. It should find the first nonempty buffer: https://github.com/rust-lang/rust/blob/master/src/libstd/io/mod.rs#L535-L537

@sfackler
Copy link
Member Author

sfackler commented Mar 8, 2019

#59009

@carllerche
Copy link
Member

I plan on issuing breaking change releases of a bunch of crates around the time async / await is stabilized. This will include crates that currently depend on iovec. It would be nice to be able to switch to the types in std. That would require iovec hitting stable around the same time as Future.

@alexcrichton
Copy link
Member

@rfcbot fcp merge

I continue to at least personally be confident in this approach for implementing vectored I/O in the standard library, so I'd like to propose that we stabilize this. With #59852 I believe we've also implemented it for all necessary types and such in the standard library.

@rfcbot
Copy link

rfcbot commented Apr 10, 2019

Team member @alexcrichton has proposed to merge this. The next step is review by the rest of the tagged team members:

Concerns:

Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!

See this document for info about what commands tagged team members can give me.

@rfcbot rfcbot added proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. labels Apr 10, 2019
@SimonSapin
Copy link
Contributor

As of this writing, these are the APIs in master that point here:

pub struct IoVec<'a>();
pub struct IoVecMut<'a>();

impl<'a> fmt::Debug for IoVec<'a> {}
impl<'a> fmt::Debug for IoVecMut<'a> {}

impl<'a> IoVec<'a> {
    pub fn new(buf: &'a [u8]) -> Self {}
}
impl<'a> IoVecMut<'a> {
    pub fn new(buf: &'a mut [u8]) -> Self {}
}

impl<'a> Deref for IoVec<'a> {
    type Target = [u8];
}
impl<'a> Deref for IoVecMut<'a> {
    type Target = [u8];
}
impl<'a> DerefMut for IoVecMut<'a> {}

pub trait Write {
    fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> Result<usize> {}
}
pub trait Read {
    fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> Result<usize> {}
}

@rfcbot rfcbot added final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. and removed proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. labels Apr 12, 2019
@rfcbot
Copy link

rfcbot commented Apr 12, 2019

🔔 This is now entering its final comment period, as per the review above. 🔔

@withoutboats
Copy link
Contributor

I wish we could have these types be written as DSTs, but it doesn't seem realistic (given that the pointer is the second value on some platforms) or worth blocking on.

@withoutboats
Copy link
Contributor

@rfcbot concern name

I want to raise a question actually: is iovec the right name for these types? We've just taken the name used by UNIX, which is something in the past we moved away from (renaming the various fs functions for example). In particular, I think IoVec is somewhat confusing because in Rust its pretty established that Vec specifically means our heap allocated buffer type. Perhaps it would be wise to rename them?

@rfcbot rfcbot added proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. and removed final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. labels Apr 15, 2019
@alexcrichton
Copy link
Member

That's true! @withoutboats do you have ideas for alternative names? I think one possibility is IoBuf but that doesn't jive well with PathBuf which is allocated on the heap as well. We could go with longer names as well like IoSlice or VectoredSlice as well perhaps?

@Amanieu
Copy link
Member

Amanieu commented Apr 15, 2019

IoGather/IoScatter? And rename the functions to write_gather/read_scatter.

@sfackler
Copy link
Member Author

WsaBuf!

But yeah, something that indicates that it's a slice seems like a good idea.

@SimonSapin
Copy link
Contributor

+1 for IoSlice, as it converts to and from a slice (of bytes).

I’m not sure how Vectored would be meaningful: as I read it the vec in iovec refers to a vector of bytes, not to the fact that you typically use more than one of them at a time. In the man page:

The pointer iov points to an array of iovec structures

… it’s each item of the “outer” array that’s called iovec, not the array itself.

@sfackler
Copy link
Member Author

IoSlice/IoSliceMut or GatherBuf/ScatterBuf seem reasonable to me.

@alexcrichton
Copy link
Member

I've personally always been slightly confused with the gather/scatter terminology although if I sit down and think hard about it then it makes sense. I'm warming up personally to IoSlice and IoSliceMut, and I think that'd jive well with the types themselves as we in theory want the APIs to take &[&[u8]] and &mut [&mut [u8]], but we need a platform-specific representation of the inner elements hence the Io part, but they're still slices

@withoutboats
Copy link
Contributor

Yea I was thinking either IoSlice or IoBuf and the PathBuf thing puts it over the edge to the former I think.

I'd propose we change the name to ioslice and also make sure the docs for the two types are clear that they correspond to iovec on unix and wsabuf on windows.

@sfackler
Copy link
Member Author

👍

The docs do already mention the iovec/WSABUF correspondence, but it could probably be called out better: https://doc.rust-lang.org/std/io/struct.IoVec.html

@withoutboats
Copy link
Contributor

@rfcbot resolve name

@rfcbot rfcbot added final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. and removed proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. labels Apr 15, 2019
@rfcbot
Copy link

rfcbot commented Apr 15, 2019

🔔 This is now entering its final comment period, as per the review above. 🔔

@carllerche
Copy link
Member

If the type does not use Vec in the name, should the fns use a different suffix than vectored?

@sfackler
Copy link
Member Author

read_scatter and write_gather would probably be the other option.

@alexcrichton
Copy link
Member

I would disagree that we need to rename the _vectored suffix on these methods because "vectored" is pretty different than Vec which is very well known in Rust. AFAIK the terminology for this form of I/O is either "vectored I/O" or "scatter/gather I/O", so having a suffix of "vectored" I don't think will lead to undue confusion that Vec should be involved somehow, especially when we already have read_to_vec which hasn't been historically confused for vectored I/O

@rfcbot rfcbot added the finished-final-comment-period The final comment period is finished for this PR / Issue. label Apr 25, 2019
@rfcbot
Copy link

rfcbot commented Apr 25, 2019

The final comment period, with a disposition to merge, as per the review above, is now complete.

As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed.

The RFC will be merged soon.

@rfcbot rfcbot removed the final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. label Apr 25, 2019
@sfackler
Copy link
Member Author

So it sounds like the changes we want to make are IoVec/IoVecMut -> IoSlice/IoSliceMut, and we'll retain the current name of the methods. Is that correct?

I'll make a stabilization PR if so.

@alexcrichton
Copy link
Member

That was my read on this as well! And thanks @sfackler!

sfackler added a commit to sfackler/rust that referenced this issue Apr 27, 2019
This renames `std::io::IoVec` to `std::io::IoSlice` and
`std::io::IoVecMut` to `std::io::IoSliceMut`, and stabilizes
`std::io::IoSlice`, `std::io::IoSliceMut`,
`std::io::Read::read_vectored`, and `std::io::Write::write_vectored`.

Closes rust-lang#58452
Centril added a commit to Centril/rust that referenced this issue Apr 29, 2019
Stabilized vectored IO

This renames `std::io::IoVec` to `std::io::IoSlice` and
`std::io::IoVecMut` to `std::io::IoSliceMut`, and stabilizes
`std::io::IoSlice`, `std::io::IoSliceMut`,
`std::io::Read::read_vectored`, and `std::io::Write::write_vectored`.

Closes rust-lang#58452

r? @alexcrichton
@RReverser
Copy link
Contributor

Would it be worth to add write_vectored_all or is it out of scope of stdlib API?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
B-unstable Blocker: Implemented in the nightly compiler and unstable. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. finished-final-comment-period The final comment period is finished for this PR / Issue. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.