Skip to content

Commit c4d9f42

Browse files
authored
Rollup merge of #67841 - sfackler:can-vector, r=Amaneiu
Add Read/Write::can_read/write_vectored When working with an arbitrary reader or writer, code that uses vectored operations may end up being slower than code that copies into a single buffer when the underlying reader or writer doesn't actually support vectored operations. These new methods allow you to ask the reader or witer up front if vectored operations are efficiently supported. Currently, you have to use some heuristics to guess by e.g. checking if the read or write only accessed the first buffer. Hyper is one concrete example of a library that has to do this dynamically: https://github.com/hyperium/hyper/blob/0eaf304644a396895a4ce1f0146e596640bb666a/src/proto/h1/io.rs#L582-L594
2 parents 46ec74e + c68f23f commit c4d9f42

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+565
-0
lines changed

src/libstd/fs.rs

+20
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,11 @@ impl Read for File {
659659
self.inner.read_vectored(bufs)
660660
}
661661

662+
#[inline]
663+
fn is_read_vectored(&self) -> bool {
664+
self.inner.is_read_vectored()
665+
}
666+
662667
#[inline]
663668
unsafe fn initializer(&self) -> Initializer {
664669
Initializer::nop()
@@ -674,6 +679,11 @@ impl Write for File {
674679
self.inner.write_vectored(bufs)
675680
}
676681

682+
#[inline]
683+
fn is_write_vectored(&self) -> bool {
684+
self.inner.is_write_vectored()
685+
}
686+
677687
fn flush(&mut self) -> io::Result<()> {
678688
self.inner.flush()
679689
}
@@ -694,6 +704,11 @@ impl Read for &File {
694704
self.inner.read_vectored(bufs)
695705
}
696706

707+
#[inline]
708+
fn is_read_vectored(&self) -> bool {
709+
self.inner.is_read_vectored()
710+
}
711+
697712
#[inline]
698713
unsafe fn initializer(&self) -> Initializer {
699714
Initializer::nop()
@@ -709,6 +724,11 @@ impl Write for &File {
709724
self.inner.write_vectored(bufs)
710725
}
711726

727+
#[inline]
728+
fn is_write_vectored(&self) -> bool {
729+
self.inner.is_write_vectored()
730+
}
731+
712732
fn flush(&mut self) -> io::Result<()> {
713733
self.inner.flush()
714734
}

src/libstd/io/buffered.rs

+8
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,10 @@ impl<R: Read> Read for BufReader<R> {
292292
Ok(nread)
293293
}
294294

295+
fn is_read_vectored(&self) -> bool {
296+
self.inner.is_read_vectored()
297+
}
298+
295299
// we can't skip unconditionally because of the large buffer case in read.
296300
unsafe fn initializer(&self) -> Initializer {
297301
self.inner.initializer()
@@ -680,6 +684,10 @@ impl<W: Write> Write for BufWriter<W> {
680684
}
681685
}
682686

687+
fn is_write_vectored(&self) -> bool {
688+
self.get_ref().is_write_vectored()
689+
}
690+
683691
fn flush(&mut self) -> io::Result<()> {
684692
self.flush_buf().and_then(|()| self.get_mut().flush())
685693
}

src/libstd/io/cursor.rs

+24
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,10 @@ where
266266
Ok(nread)
267267
}
268268

269+
fn is_read_vectored(&self) -> bool {
270+
true
271+
}
272+
269273
fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
270274
let n = buf.len();
271275
Read::read_exact(&mut self.fill_buf()?, buf)?;
@@ -372,6 +376,11 @@ impl Write for Cursor<&mut [u8]> {
372376
slice_write_vectored(&mut self.pos, self.inner, bufs)
373377
}
374378

379+
#[inline]
380+
fn is_write_vectored(&self) -> bool {
381+
true
382+
}
383+
375384
#[inline]
376385
fn flush(&mut self) -> io::Result<()> {
377386
Ok(())
@@ -388,6 +397,11 @@ impl Write for Cursor<&mut Vec<u8>> {
388397
vec_write_vectored(&mut self.pos, self.inner, bufs)
389398
}
390399

400+
#[inline]
401+
fn is_write_vectored(&self) -> bool {
402+
true
403+
}
404+
391405
#[inline]
392406
fn flush(&mut self) -> io::Result<()> {
393407
Ok(())
@@ -404,6 +418,11 @@ impl Write for Cursor<Vec<u8>> {
404418
vec_write_vectored(&mut self.pos, &mut self.inner, bufs)
405419
}
406420

421+
#[inline]
422+
fn is_write_vectored(&self) -> bool {
423+
true
424+
}
425+
407426
#[inline]
408427
fn flush(&mut self) -> io::Result<()> {
409428
Ok(())
@@ -422,6 +441,11 @@ impl Write for Cursor<Box<[u8]>> {
422441
slice_write_vectored(&mut self.pos, &mut self.inner, bufs)
423442
}
424443

444+
#[inline]
445+
fn is_write_vectored(&self) -> bool {
446+
true
447+
}
448+
425449
#[inline]
426450
fn flush(&mut self) -> io::Result<()> {
427451
Ok(())

src/libstd/io/impls.rs

+35
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ impl<R: Read + ?Sized> Read for &mut R {
2020
(**self).read_vectored(bufs)
2121
}
2222

23+
#[inline]
24+
fn is_read_vectored(&self) -> bool {
25+
(**self).is_read_vectored()
26+
}
27+
2328
#[inline]
2429
unsafe fn initializer(&self) -> Initializer {
2530
(**self).initializer()
@@ -52,6 +57,11 @@ impl<W: Write + ?Sized> Write for &mut W {
5257
(**self).write_vectored(bufs)
5358
}
5459

60+
#[inline]
61+
fn is_write_vectored(&self) -> bool {
62+
(**self).is_write_vectored()
63+
}
64+
5565
#[inline]
5666
fn flush(&mut self) -> io::Result<()> {
5767
(**self).flush()
@@ -109,6 +119,11 @@ impl<R: Read + ?Sized> Read for Box<R> {
109119
(**self).read_vectored(bufs)
110120
}
111121

122+
#[inline]
123+
fn is_read_vectored(&self) -> bool {
124+
(**self).is_read_vectored()
125+
}
126+
112127
#[inline]
113128
unsafe fn initializer(&self) -> Initializer {
114129
(**self).initializer()
@@ -141,6 +156,11 @@ impl<W: Write + ?Sized> Write for Box<W> {
141156
(**self).write_vectored(bufs)
142157
}
143158

159+
#[inline]
160+
fn is_write_vectored(&self) -> bool {
161+
(**self).is_write_vectored()
162+
}
163+
144164
#[inline]
145165
fn flush(&mut self) -> io::Result<()> {
146166
(**self).flush()
@@ -240,6 +260,11 @@ impl Read for &[u8] {
240260
Ok(nread)
241261
}
242262

263+
#[inline]
264+
fn is_read_vectored(&self) -> bool {
265+
true
266+
}
267+
243268
#[inline]
244269
unsafe fn initializer(&self) -> Initializer {
245270
Initializer::nop()
@@ -316,6 +341,11 @@ impl Write for &mut [u8] {
316341
Ok(nwritten)
317342
}
318343

344+
#[inline]
345+
fn is_write_vectored(&self) -> bool {
346+
true
347+
}
348+
319349
#[inline]
320350
fn write_all(&mut self, data: &[u8]) -> io::Result<()> {
321351
if self.write(data)? == data.len() {
@@ -351,6 +381,11 @@ impl Write for Vec<u8> {
351381
Ok(len)
352382
}
353383

384+
#[inline]
385+
fn is_write_vectored(&self) -> bool {
386+
true
387+
}
388+
354389
#[inline]
355390
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
356391
self.extend_from_slice(buf);

src/libstd/io/mod.rs

+27
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@
256256
//! [`Read::read`]: trait.Read.html#tymethod.read
257257
//! [`Result`]: ../result/enum.Result.html
258258
//! [`.unwrap()`]: ../result/enum.Result.html#method.unwrap
259+
// ignore-tidy-filelength
259260

260261
#![stable(feature = "rust1", since = "1.0.0")]
261262

@@ -580,6 +581,19 @@ pub trait Read {
580581
default_read_vectored(|b| self.read(b), bufs)
581582
}
582583

584+
/// Determines if this `Read`er has an efficient `read_vectored`
585+
/// implementation.
586+
///
587+
/// If a `Read`er does not override the default `read_vectored`
588+
/// implementation, code using it may want to avoid the method all together
589+
/// and coalesce writes into a single buffer for higher performance.
590+
///
591+
/// The default implementation returns `false`.
592+
#[unstable(feature = "can_vector", issue = "69941")]
593+
fn is_read_vectored(&self) -> bool {
594+
false
595+
}
596+
583597
/// Determines if this `Read`er can work with buffers of uninitialized
584598
/// memory.
585599
///
@@ -1304,6 +1318,19 @@ pub trait Write {
13041318
default_write_vectored(|b| self.write(b), bufs)
13051319
}
13061320

1321+
/// Determines if this `Write`er has an efficient `write_vectored`
1322+
/// implementation.
1323+
///
1324+
/// If a `Write`er does not override the default `write_vectored`
1325+
/// implementation, code using it may want to avoid the method all together
1326+
/// and coalesce writes into a single buffer for higher performance.
1327+
///
1328+
/// The default implementation returns `false`.
1329+
#[unstable(feature = "can_vector", issue = "69941")]
1330+
fn is_write_vectored(&self) -> bool {
1331+
false
1332+
}
1333+
13071334
/// Flush this output stream, ensuring that all intermediately buffered
13081335
/// contents reach their destination.
13091336
///

src/libstd/io/stdio.rs

+56
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ impl Read for StdinRaw {
8787
self.0.read_vectored(bufs)
8888
}
8989

90+
#[inline]
91+
fn is_read_vectored(&self) -> bool {
92+
self.0.is_read_vectored()
93+
}
94+
9095
#[inline]
9196
unsafe fn initializer(&self) -> Initializer {
9297
Initializer::nop()
@@ -101,6 +106,11 @@ impl Write for StdoutRaw {
101106
self.0.write_vectored(bufs)
102107
}
103108

109+
#[inline]
110+
fn is_write_vectored(&self) -> bool {
111+
self.0.is_write_vectored()
112+
}
113+
104114
fn flush(&mut self) -> io::Result<()> {
105115
self.0.flush()
106116
}
@@ -114,6 +124,11 @@ impl Write for StderrRaw {
114124
self.0.write_vectored(bufs)
115125
}
116126

127+
#[inline]
128+
fn is_write_vectored(&self) -> bool {
129+
self.0.is_write_vectored()
130+
}
131+
117132
fn flush(&mut self) -> io::Result<()> {
118133
self.0.flush()
119134
}
@@ -140,6 +155,14 @@ impl<W: io::Write> io::Write for Maybe<W> {
140155
}
141156
}
142157

158+
#[inline]
159+
fn is_write_vectored(&self) -> bool {
160+
match self {
161+
Maybe::Real(w) => w.is_write_vectored(),
162+
Maybe::Fake => true,
163+
}
164+
}
165+
143166
fn flush(&mut self) -> io::Result<()> {
144167
match *self {
145168
Maybe::Real(ref mut w) => handle_ebadf(w.flush(), ()),
@@ -162,6 +185,14 @@ impl<R: io::Read> io::Read for Maybe<R> {
162185
Maybe::Fake => Ok(0),
163186
}
164187
}
188+
189+
#[inline]
190+
fn is_read_vectored(&self) -> bool {
191+
match self {
192+
Maybe::Real(w) => w.is_read_vectored(),
193+
Maybe::Fake => true,
194+
}
195+
}
165196
}
166197

167198
fn handle_ebadf<T>(r: io::Result<T>, default: T) -> io::Result<T> {
@@ -352,6 +383,10 @@ impl Read for Stdin {
352383
self.lock().read_vectored(bufs)
353384
}
354385
#[inline]
386+
fn is_read_vectored(&self) -> bool {
387+
self.lock().is_read_vectored()
388+
}
389+
#[inline]
355390
unsafe fn initializer(&self) -> Initializer {
356391
Initializer::nop()
357392
}
@@ -376,6 +411,11 @@ impl Read for StdinLock<'_> {
376411
self.inner.read_vectored(bufs)
377412
}
378413

414+
#[inline]
415+
fn is_read_vectored(&self) -> bool {
416+
self.inner.is_read_vectored()
417+
}
418+
379419
#[inline]
380420
unsafe fn initializer(&self) -> Initializer {
381421
Initializer::nop()
@@ -543,6 +583,10 @@ impl Write for Stdout {
543583
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
544584
self.lock().write_vectored(bufs)
545585
}
586+
#[inline]
587+
fn is_write_vectored(&self) -> bool {
588+
self.lock().is_write_vectored()
589+
}
546590
fn flush(&mut self) -> io::Result<()> {
547591
self.lock().flush()
548592
}
@@ -561,6 +605,10 @@ impl Write for StdoutLock<'_> {
561605
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
562606
self.inner.borrow_mut().write_vectored(bufs)
563607
}
608+
#[inline]
609+
fn is_write_vectored(&self) -> bool {
610+
self.inner.borrow_mut().is_write_vectored()
611+
}
564612
fn flush(&mut self) -> io::Result<()> {
565613
self.inner.borrow_mut().flush()
566614
}
@@ -709,6 +757,10 @@ impl Write for Stderr {
709757
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
710758
self.lock().write_vectored(bufs)
711759
}
760+
#[inline]
761+
fn is_write_vectored(&self) -> bool {
762+
self.lock().is_write_vectored()
763+
}
712764
fn flush(&mut self) -> io::Result<()> {
713765
self.lock().flush()
714766
}
@@ -727,6 +779,10 @@ impl Write for StderrLock<'_> {
727779
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
728780
self.inner.borrow_mut().write_vectored(bufs)
729781
}
782+
#[inline]
783+
fn is_write_vectored(&self) -> bool {
784+
self.inner.borrow_mut().is_write_vectored()
785+
}
730786
fn flush(&mut self) -> io::Result<()> {
731787
self.inner.borrow_mut().flush()
732788
}

0 commit comments

Comments
 (0)