Last active
January 15, 2016 13:01
-
-
Save psychoss/faba75f648e932cf0f51 to your computer and use it in GitHub Desktop.
Rust Performance
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-> % cat src/main.rs | |
extern crate time; | |
use std::env; | |
use std::ptr; | |
use time::Duration; | |
const SIZE: usize = 10 * 1024 * 1024; | |
fn copy_iter(src: &[u8], dst: &mut Vec<u8>) { | |
// dst.extend(src.iter()) | |
for &byte in src { | |
dst.push(byte); | |
} | |
} | |
fn copy_index(src: &[u8], dst: &mut Vec<u8>) { | |
let mut index = 0; | |
unsafe { dst.set_len(SIZE); } | |
while index < src.len() { | |
dst[index] = src[index]; | |
index += 1; | |
} | |
} | |
// I'm using stable Rust, so I don't have extend_from_slice | |
// fn copy_push_all(src: &[u8], dst: &mut Vec<u8>) { | |
// dst.extend_from_slice(src); | |
// } | |
fn copy_ptr(src: &[u8], dst: &mut Vec<u8>) { | |
unsafe { | |
dst.set_len(SIZE); | |
ptr::copy_nonoverlapping(src.as_ptr(), (&mut dst[..]).as_mut_ptr(), SIZE); | |
} | |
} | |
fn main() { | |
let args: Vec<_> = env::args().collect(); | |
if args.len() < 2 { | |
panic!("Provide method") | |
} | |
let src = vec![1; SIZE]; | |
let mut dst = Vec::with_capacity(SIZE); | |
println!("{}", Duration::span(|| { | |
match &(args[1])[..] { | |
"iter" => copy_iter(&src[..], &mut dst), | |
"index" => copy_index(&src[..], &mut dst), | |
// "push_all" => copy_push_all(&src[..], &mut dst), | |
"ptr" => copy_ptr(&src[..], &mut dst), | |
_ => println!("Wrong method"), | |
} | |
})); | |
println!("{:?}", &dst[..10]); | |
} | |
-> % cargo build --release | |
Compiling bench v0.1.0 (file:///home/matklad/trash/bench) | |
-> % cargo run --release -- iter | |
Running `target/release/bench iter` | |
PT0.030518169S | |
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1] | |
-> % cargo run --release -- iter | |
Running `target/release/bench iter` | |
PT0.029139180S | |
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1] | |
-> % cargo run --release -- iter | |
Running `target/release/bench iter` | |
PT0.029092613S | |
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1] | |
-> % cargo run --release -- index | |
Running `target/release/bench index` | |
PT0.004216764S | |
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1] | |
-> % cargo run --release -- index | |
Running `target/release/bench index` | |
PT0.004246780S | |
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1] | |
-> % cargo run --release -- index | |
Running `target/release/bench index` | |
PT0.004236901S | |
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1] | |
-> % cat src/main.rs | |
extern crate time; | |
use std::env; | |
use std::ptr; | |
use time::Duration; | |
const SIZE: usize = 10 * 1024 * 1024; | |
fn copy_iter(src: &[u8], dst: &mut Vec<u8>) { | |
dst.extend(src.iter()) | |
// for &byte in src { | |
// dst.push(byte); | |
// } | |
} | |
fn copy_index(src: &[u8], dst: &mut Vec<u8>) { | |
let mut index = 0; | |
unsafe { dst.set_len(SIZE); } | |
while index < src.len() { | |
dst[index] = src[index]; | |
index += 1; | |
} | |
} | |
// I'm using stable Rust, so I don't have extend_from_slice | |
// fn copy_push_all(src: &[u8], dst: &mut Vec<u8>) { | |
// dst.extend_from_slice(src); | |
// } | |
fn copy_ptr(src: &[u8], dst: &mut Vec<u8>) { | |
unsafe { | |
dst.set_len(SIZE); | |
ptr::copy_nonoverlapping(src.as_ptr(), (&mut dst[..]).as_mut_ptr(), SIZE); | |
} | |
} | |
fn main() { | |
let args: Vec<_> = env::args().collect(); | |
if args.len() < 2 { | |
panic!("Provide method") | |
} | |
let src = vec![1; SIZE]; | |
let mut dst = Vec::with_capacity(SIZE); | |
println!("{}", Duration::span(|| { | |
match &(args[1])[..] { | |
"iter" => copy_iter(&src[..], &mut dst), | |
"index" => copy_index(&src[..], &mut dst), | |
// "push_all" => copy_push_all(&src[..], &mut dst), | |
"ptr" => copy_ptr(&src[..], &mut dst), | |
_ => println!("Wrong method"), | |
} | |
})); | |
println!("{:?}", &dst[..10]); | |
} | |
-> % cargo build --release | |
Compiling bench v0.1.0 (file:///home/matklad/trash/bench) | |
-> % cargo run --release -- iter | |
Running `target/release/bench iter` | |
PT0.023198766S | |
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1] | |
-> % cargo run --release -- iter | |
Running `target/release/bench iter` | |
PT0.023328732S | |
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1] | |
-> % cargo run --release -- iter | |
Running `target/release/bench iter` | |
PT0.023282794S | |
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1] | |
-> % cargo run --release -- index | |
Running `target/release/bench index` | |
PT0.013653107S | |
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1] | |
-> % cargo run --release -- index | |
Running `target/release/bench index` | |
PT0.013599356S | |
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1] | |
-> % cargo run --release -- index | |
Running `target/release/bench index` | |
PT0.013615311S | |
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::io::Write; | |
/// Copy data in `from` into `to`, until the shortest | |
/// of the two slices. | |
/// | |
/// Return the number of bytes written. | |
fn byte_copy(from: &[u8], mut to: &mut [u8]) -> usize { | |
to.write(&from).unwrap() | |
} | |
fn main() { | |
let source = [1, 2, 3, 4, 5, 6u8]; | |
let mut dest = [0u8; 16]; | |
byte_copy(&source, &mut dest); | |
println!("{:?}", dest); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extern crate time; | |
use std::env; | |
use std::ptr; | |
use time::Duration; | |
const SIZE: usize = 10 * 1024 * 1024; | |
fn copy_iter(src: &[u8], dst: &mut Vec<u8>) { | |
for &byte in src { | |
dst.push(byte); | |
} | |
} | |
fn copy_index(src: &[u8], dst: &mut Vec<u8>) { | |
let mut index = 0; | |
unsafe { dst.set_len(SIZE); } | |
while index < src.len() { | |
dst[index] = src[index]; | |
index += 1; | |
} | |
} | |
fn copy_push_all(src: &[u8], dst: &mut Vec<u8>) { | |
dst.extend_from_slice(src); | |
} | |
fn copy_ptr(src: &[u8], dst: &mut Vec<u8>) { | |
unsafe { | |
dst.set_len(SIZE); | |
ptr::copy_nonoverlapping(src.as_ptr(), (&mut dst[..]).as_mut_ptr(), SIZE); | |
} | |
} | |
fn main() { | |
let args: Vec<_> = env::args().collect(); | |
if args.len() < 2 { | |
panic!("Provide method") | |
} | |
let src = vec![1; SIZE]; | |
let mut dst = Vec::with_capacity(SIZE); | |
println!("{}", Duration::span(|| { | |
match &(args[1])[..] { | |
"iter" => copy_iter(&src[..], &mut dst), | |
"index" => copy_index(&src[..], &mut dst), | |
"push_all" => copy_push_all(&src[..], &mut dst), | |
"ptr" => copy_ptr(&src[..], &mut dst), | |
_ => println!("Wrong method"), | |
} | |
})); | |
println!("{:?}", &dst[..10]); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::mem::size_of; | |
use std::rc::Rc; | |
use std::sync::Arc; | |
struct Foo { | |
a: i32, | |
b: f64, | |
} | |
fn main() { | |
println!("Foo: {}", size_of::<Foo>()); | |
println!("Option<Foo>: {}", size_of::<Option<Foo>>()); | |
println!("Rc<Foo>: {}", size_of::<Rc<Foo>>()); | |
println!("Option<Rc<Foo>>: {}", size_of::<Option<Rc<Foo>>>()); | |
println!("Arc<Foo>: {}", size_of::<Arc<Foo>>()); | |
println!("Option<Arc<Foo>>: {}", size_of::<Option<Arc<Foo>>>()); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![deny(missing_docs)] | |
#![cfg_attr(feature = "unstable", feature(raw))] | |
//! Shrinks slice references | |
//! | |
//! `ResizeSlice` can be used to adjust the starting offset and length of a slice. | |
//! | |
//! ## Example | |
//! | |
//! ``` | |
//! use resize_slice::ResizeSlice; | |
//! | |
//! let mut slice: &mut [_] = &mut [1, 2, 3, 4, 5]; | |
//! slice.resize_from(2); | |
//! | |
//! assert_eq!(slice, &mut [3, 4, 5]); | |
//! ``` | |
extern crate uninitialized; | |
use std::mem::transmute; | |
use uninitialized::UNINITIALIZED; | |
use std::ptr::write_bytes; | |
/// Extension trait that allows you to resize mutable slice references | |
pub trait ResizeSlice { | |
/// Resizes the slice to `start` offset and `end - start` len | |
/// | |
/// # Panics | |
/// | |
/// Panics on out of bounds resize (`start <= end <= self.len()`) | |
fn resize(&mut self, start: usize, end: usize); | |
/// Resize to a new beginning offset | |
/// | |
/// # Panics | |
/// | |
/// Panics if `start > self.len()` | |
fn resize_from(&mut self, start: usize); | |
/// Resize to a new length | |
/// | |
/// # Panics | |
/// | |
/// Panics if `end > self.len()` | |
fn resize_to(&mut self, end: usize); | |
} | |
#[inline] | |
fn slice_resize<T>(slice: &mut Slice<T>, start: usize, end: usize) { | |
assert!(start <= end && end <= slice.len); | |
slice.data = unsafe { slice.data.offset(start as isize) }; | |
slice.len = end - start; | |
} | |
impl<'a, T> ResizeSlice for &'a mut [T] { | |
#[inline] | |
fn resize(&mut self, start: usize, end: usize) { | |
unsafe { | |
slice_resize::<T>(transmute(self), start, end); | |
} | |
} | |
#[inline] | |
fn resize_from(&mut self, start: usize) { | |
let len = self.len(); | |
self.resize(start, len); | |
} | |
#[inline] | |
fn resize_to(&mut self, end: usize) { | |
self.resize(0, end) | |
} | |
} | |
impl<'a, T> ResizeSlice for &'a [T] { | |
#[inline] | |
fn resize(&mut self, start: usize, end: usize) { | |
unsafe { | |
slice_resize::<T>(transmute(self), start, end); | |
} | |
} | |
#[inline] | |
fn resize_from(&mut self, start: usize) { | |
let len = self.len(); | |
self.resize(start, len); | |
} | |
#[inline] | |
fn resize_to(&mut self, end: usize) { | |
self.resize(0, end) | |
} | |
} | |
#[cfg(feature = "unstable")] | |
use std::raw::Slice; | |
#[cfg(not(feature = "unstable"))] | |
struct Slice<T> { | |
data: *const T, | |
len: usize, | |
} | |
/// Extension methods for vector types | |
pub trait VecExt<T> { | |
/// Unsafely a vector to the specified size, without initializing the memory. | |
unsafe fn uninitialized_resize(&mut self, new_len: usize); | |
/// Unsafely a vector to the specified size, zeroing the memory. | |
unsafe fn zeroed_resize(&mut self, new_len: usize); | |
} | |
/// Extension methods for slices | |
pub trait SliceExt<T> { | |
/// Copies the less of `self.len()` and `src.len()` from `src` into `self`, | |
/// returning the amount of items copies. | |
fn copy_from(&mut self, src: &[T]) -> usize where T: Copy; | |
/// Copies elements to another location within the slice, which may overlap. | |
fn copy_inner(&mut self, src: usize, dst: usize, len: usize) where T: Copy; | |
} | |
impl<T> SliceExt<T> for [T] { | |
#[inline] | |
fn copy_from(&mut self, src: &[T]) -> usize where T: Copy { | |
use std::ptr::copy_nonoverlapping; | |
use std::cmp::min; | |
let len = min(self.len(), src.len()); | |
unsafe { | |
copy_nonoverlapping(src.as_ptr(), self.as_mut_ptr(), len); | |
} | |
len | |
} | |
#[inline] | |
fn copy_inner(&mut self, src: usize, dst: usize, len: usize) where T: Copy { | |
use std::ptr::copy; | |
assert!(self.len() - len >= src && self.len() - len >= dst); | |
unsafe { | |
copy(self.as_ptr().offset(src as isize), self.as_mut_ptr().offset(dst as isize), len); | |
} | |
} | |
} | |
impl<T> VecExt<T> for Vec<T> { | |
#[inline] | |
unsafe fn uninitialized_resize(&mut self, new_len: usize) { | |
let len = self.len(); | |
if new_len > len { | |
self.reserve_exact(new_len - len); | |
} | |
self.set_len(new_len); | |
} | |
#[inline] | |
unsafe fn zeroed_resize(&mut self, new_len: usize) { | |
self.uninitialized_resize(new_len); | |
if !UNINITIALIZED { | |
write_bytes(self.as_mut_ptr(), 0, new_len); | |
} | |
} | |
} | |
#[cfg(feature = "smallvec")] | |
mod smallvec_impl { | |
extern crate smallvec; | |
use self::smallvec::{SmallVec, Array}; | |
use std::ptr::write_bytes; | |
use uninitialized::UNINITIALIZED; | |
use super::VecExt; | |
impl<T: Array> VecExt<T::Item> for SmallVec<T> { | |
#[inline] | |
unsafe fn uninitialized_resize(&mut self, new_len: usize) { | |
let len = self.len(); | |
if new_len > len { | |
self.reserve_exact(new_len - len); | |
} | |
self.set_len(new_len); | |
} | |
#[inline] | |
unsafe fn zeroed_resize(&mut self, new_len: usize) { | |
self.uninitialized_resize(new_len); | |
if !UNINITIALIZED { | |
write_bytes(self.as_mut_ptr(), 0, new_len); | |
} | |
} | |
} | |
} | |
#[test] | |
fn resize() { | |
let mut s: &mut [_] = &mut [1, 2, 3]; | |
assert_eq!(s.len(), 3); | |
s.resize_from(1); | |
assert_eq!(s.len(), 2); | |
s.resize_to(1); | |
assert_eq!(s.len(), 1); | |
assert_eq!(s[0], 2); | |
s.resize(1, 1); | |
assert_eq!(s.len(), 0); | |
} | |
#[test] | |
#[should_panic] | |
fn resize_fail() { | |
let mut s: &mut [_] = &mut [1, 2, 3]; | |
s.resize_to(4); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment