Skip to content

Instantly share code, notes, and snippets.

@psychoss
Last active January 15, 2016 13:01
Show Gist options
  • Save psychoss/faba75f648e932cf0f51 to your computer and use it in GitHub Desktop.
Save psychoss/faba75f648e932cf0f51 to your computer and use it in GitHub Desktop.
Rust Performance
-> % 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]
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);
}
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]);
}
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>>>());
}
#![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