mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +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::fmt;
|
||||||
use core::hash::{self, Hash};
|
use core::hash::{self, Hash};
|
||||||
use core::intrinsics::{arith_offset, assume};
|
use core::intrinsics::{arith_offset, assume};
|
||||||
use core::iter::{repeat, FromIterator};
|
use core::iter::FromIterator;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use core::mem;
|
use core::mem;
|
||||||
use core::ops::{Index, IndexMut, Deref};
|
use core::ops::{Index, IndexMut, Deref};
|
||||||
@ -1106,12 +1106,35 @@ impl<T: Clone> Vec<T> {
|
|||||||
let len = self.len();
|
let len = self.len();
|
||||||
|
|
||||||
if new_len > len {
|
if new_len > len {
|
||||||
self.extend(repeat(value).take(new_len - len));
|
self.extend_with_element(new_len - len, value);
|
||||||
} else {
|
} else {
|
||||||
self.truncate(new_len);
|
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`.
|
/// Appends all elements in a slice to the `Vec`.
|
||||||
///
|
///
|
||||||
/// Iterates over the slice `other`, clones each element, and then appends
|
/// 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)]
|
#[doc(hidden)]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn from_elem<T: Clone>(elem: T, n: usize) -> Vec<T> {
|
pub fn from_elem<T: Clone>(elem: T, n: usize) -> Vec<T> {
|
||||||
unsafe {
|
let mut v = Vec::with_capacity(n);
|
||||||
let mut v = Vec::with_capacity(n);
|
v.extend_with_element(n, elem);
|
||||||
let mut ptr = v.as_mut_ptr();
|
v
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -19,7 +19,6 @@ use error;
|
|||||||
use fmt;
|
use fmt;
|
||||||
use io::{self, DEFAULT_BUF_SIZE, Error, ErrorKind, SeekFrom};
|
use io::{self, DEFAULT_BUF_SIZE, Error, ErrorKind, SeekFrom};
|
||||||
use ptr;
|
use ptr;
|
||||||
use iter;
|
|
||||||
|
|
||||||
/// Wraps a `Read` and buffers input from it.
|
/// 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.
|
/// Creates a new `BufReader` with the specified buffer capacity.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn with_capacity(cap: usize, inner: R) -> BufReader<R> {
|
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 {
|
BufReader {
|
||||||
inner: inner,
|
inner: inner,
|
||||||
buf: buf,
|
buf: vec![0; cap],
|
||||||
pos: 0,
|
pos: 0,
|
||||||
cap: 0,
|
cap: 0,
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ use cmp;
|
|||||||
use rustc_unicode::str as core_str;
|
use rustc_unicode::str as core_str;
|
||||||
use error as std_error;
|
use error as std_error;
|
||||||
use fmt;
|
use fmt;
|
||||||
use iter::{self, Iterator, Extend};
|
use iter::{Iterator};
|
||||||
use marker::Sized;
|
use marker::Sized;
|
||||||
use ops::{Drop, FnOnce};
|
use ops::{Drop, FnOnce};
|
||||||
use option::Option::{self, Some, None};
|
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 {
|
if new_write_size < DEFAULT_BUF_SIZE {
|
||||||
new_write_size *= 2;
|
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..]) {
|
match r.read(&mut buf[len..]) {
|
||||||
@ -984,6 +984,14 @@ mod tests {
|
|||||||
let mut v = Vec::new();
|
let mut v = Vec::new();
|
||||||
assert_eq!(c.read_to_end(&mut v).unwrap(), 1);
|
assert_eq!(c.read_to_end(&mut v).unwrap(), 1);
|
||||||
assert_eq!(v, b"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]
|
#[test]
|
||||||
|
@ -146,6 +146,7 @@
|
|||||||
#![feature(unique)]
|
#![feature(unique)]
|
||||||
#![feature(unsafe_no_drop_flag, filling_drop)]
|
#![feature(unsafe_no_drop_flag, filling_drop)]
|
||||||
#![feature(vec_push_all)]
|
#![feature(vec_push_all)]
|
||||||
|
#![feature(vec_resize)]
|
||||||
#![feature(wrapping)]
|
#![feature(wrapping)]
|
||||||
#![feature(zero_one)]
|
#![feature(zero_one)]
|
||||||
#![cfg_attr(windows, feature(str_utf16))]
|
#![cfg_attr(windows, feature(str_utf16))]
|
||||||
|
Loading…
Reference in New Issue
Block a user