Auto merge of #26849 - bluss:read-to-end-memset, r=alexcrichton

Improve zerofill in Vec::resize and Read::read_to_end

We needed a more efficient way to zerofill the vector in read_to_end.
This to reduce the memory intialization overhead to a minimum.

Use the implementation of `std::vec::from_elem` (used for the vec![]
macro) for Vec::resize as well. For simple element types like u8, this
compiles to memset, so it makes Vec::resize much more efficient.
This commit is contained in:
bors 2015-07-08 21:12:54 +00:00
commit 020d201a66
4 changed files with 40 additions and 27 deletions

View File

@ -67,7 +67,7 @@ use core::cmp::Ordering;
use core::fmt;
use core::hash::{self, Hash};
use core::intrinsics::{arith_offset, assume};
use core::iter::{repeat, FromIterator};
use core::iter::FromIterator;
use core::marker::PhantomData;
use core::mem;
use core::ops::{Index, IndexMut, Deref};
@ -1106,12 +1106,35 @@ impl<T: Clone> Vec<T> {
let len = self.len();
if new_len > len {
self.extend(repeat(value).take(new_len - len));
self.extend_with_element(new_len - len, value);
} else {
self.truncate(new_len);
}
}
/// Extend the vector by `n` additional clones of `value`.
fn extend_with_element(&mut self, n: usize, value: T) {
self.reserve(n);
unsafe {
let len = self.len();
let mut ptr = self.as_mut_ptr().offset(len as isize);
// Write all elements except the last one
for i in 1..n {
ptr::write(ptr, value.clone());
ptr = ptr.offset(1);
// Increment the length in every step in case clone() panics
self.set_len(len + i);
}
if n > 0 {
// We can write the last element directly without cloning needlessly
ptr::write(ptr, value);
self.set_len(len + n);
}
}
}
/// Appends all elements in a slice to the `Vec`.
///
/// Iterates over the slice `other`, clones each element, and then appends
@ -1294,25 +1317,9 @@ unsafe fn dealloc<T>(ptr: *mut T, len: usize) {
#[doc(hidden)]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn from_elem<T: Clone>(elem: T, n: usize) -> Vec<T> {
unsafe {
let mut v = Vec::with_capacity(n);
let mut ptr = v.as_mut_ptr();
// Write all elements except the last one
for i in 1..n {
ptr::write(ptr, Clone::clone(&elem));
ptr = ptr.offset(1);
v.set_len(i); // Increment the length in every step in case Clone::clone() panics
}
if n > 0 {
// We can write the last element directly without cloning needlessly
ptr::write(ptr, elem);
v.set_len(n);
}
v
}
let mut v = Vec::with_capacity(n);
v.extend_with_element(n, elem);
v
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -19,7 +19,6 @@ use error;
use fmt;
use io::{self, DEFAULT_BUF_SIZE, Error, ErrorKind, SeekFrom};
use ptr;
use iter;
/// Wraps a `Read` and buffers input from it.
///
@ -63,11 +62,9 @@ impl<R: Read> BufReader<R> {
/// Creates a new `BufReader` with the specified buffer capacity.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn with_capacity(cap: usize, inner: R) -> BufReader<R> {
let mut buf = Vec::with_capacity(cap);
buf.extend(iter::repeat(0).take(cap));
BufReader {
inner: inner,
buf: buf,
buf: vec![0; cap],
pos: 0,
cap: 0,
}

View File

@ -16,7 +16,7 @@ use cmp;
use rustc_unicode::str as core_str;
use error as std_error;
use fmt;
use iter::{self, Iterator, Extend};
use iter::{Iterator};
use marker::Sized;
use ops::{Drop, FnOnce};
use option::Option::{self, Some, None};
@ -106,7 +106,7 @@ fn read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize>
if new_write_size < DEFAULT_BUF_SIZE {
new_write_size *= 2;
}
buf.extend(iter::repeat(0).take(new_write_size));
buf.resize(len + new_write_size, 0);
}
match r.read(&mut buf[len..]) {
@ -984,6 +984,14 @@ mod tests {
let mut v = Vec::new();
assert_eq!(c.read_to_end(&mut v).unwrap(), 1);
assert_eq!(v, b"1");
let cap = 1024 * 1024;
let data = (0..cap).map(|i| (i / 3) as u8).collect::<Vec<_>>();
let mut v = Vec::new();
let (a, b) = data.split_at(data.len() / 2);
assert_eq!(Cursor::new(a).read_to_end(&mut v).unwrap(), a.len());
assert_eq!(Cursor::new(b).read_to_end(&mut v).unwrap(), b.len());
assert_eq!(v, data);
}
#[test]

View File

@ -146,6 +146,7 @@
#![feature(unique)]
#![feature(unsafe_no_drop_flag, filling_drop)]
#![feature(vec_push_all)]
#![feature(vec_resize)]
#![feature(wrapping)]
#![feature(zero_one)]
#![cfg_attr(windows, feature(str_utf16))]