mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
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:
commit
020d201a66
@ -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
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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]
|
||||
|
@ -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))]
|
||||
|
Loading…
Reference in New Issue
Block a user