Auto merge of #39645 - frewsxcv:rollup, r=frewsxcv

Rollup of 11 pull requests

- Successful merges: #39462, #39512, #39529, #39557, #39561, #39582, #39583, #39597, #39622, #39624, #39630
- Failed merges:
This commit is contained in:
bors 2017-02-08 18:11:06 +00:00
commit 4379e2fa08
58 changed files with 1922 additions and 1606 deletions

View File

@ -1,4 +1,4 @@
Version 1.15.1 (2017-02-07)
Version 1.15.1 (2017-02-08)
===========================
* [Fix IntoIter::as_mut_slice's signature][39466]

View File

@ -24,6 +24,7 @@ use Build;
pub fn clean(build: &Build) {
rm_rf(build, "tmp".as_ref());
rm_rf(build, &build.out.join("tmp"));
rm_rf(build, &build.out.join("dist"));
for host in build.config.host.iter() {
let entries = match build.out.join(host).read_dir() {

View File

@ -16,7 +16,6 @@ std_unicode = { path = "../libstd_unicode" }
name = "collectionstest"
path = "../libcollectionstest/lib.rs"
# FIXME: need to extract benchmarks to separate crate
#[[bench]]
#name = "collectionstest"
#path = "../libcollectionstest/lib.rs"
[[bench]]
name = "collectionsbenches"
path = "../libcollections/benches/lib.rs"

View File

@ -1,4 +1,4 @@
// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
@ -8,13 +8,17 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::iter::Iterator;
use std::vec::Vec;
use std::collections::BTreeMap;
use std::__rand::{Rng, thread_rng};
use test::{Bencher, black_box};
macro_rules! map_insert_rand_bench {
($name: ident, $n: expr, $map: ident) => (
#[bench]
pub fn $name(b: &mut ::test::Bencher) {
use std::__rand::{thread_rng, Rng};
use test::black_box;
pub fn $name(b: &mut Bencher) {
let n: usize = $n;
let mut map = $map::new();
// setup
@ -39,9 +43,7 @@ macro_rules! map_insert_rand_bench {
macro_rules! map_insert_seq_bench {
($name: ident, $n: expr, $map: ident) => (
#[bench]
pub fn $name(b: &mut ::test::Bencher) {
use test::black_box;
pub fn $name(b: &mut Bencher) {
let mut map = $map::new();
let n: usize = $n;
// setup
@ -64,12 +66,7 @@ macro_rules! map_insert_seq_bench {
macro_rules! map_find_rand_bench {
($name: ident, $n: expr, $map: ident) => (
#[bench]
pub fn $name(b: &mut ::test::Bencher) {
use std::iter::Iterator;
use std::__rand::{thread_rng, Rng};
use std::vec::Vec;
use test::black_box;
pub fn $name(b: &mut Bencher) {
let mut map = $map::new();
let n: usize = $n;
@ -97,9 +94,7 @@ macro_rules! map_find_rand_bench {
macro_rules! map_find_seq_bench {
($name: ident, $n: expr, $map: ident) => (
#[bench]
pub fn $name(b: &mut ::test::Bencher) {
use test::black_box;
pub fn $name(b: &mut Bencher) {
let mut map = $map::new();
let n: usize = $n;
@ -118,3 +113,45 @@ macro_rules! map_find_seq_bench {
}
)
}
map_insert_rand_bench!{insert_rand_100, 100, BTreeMap}
map_insert_rand_bench!{insert_rand_10_000, 10_000, BTreeMap}
map_insert_seq_bench!{insert_seq_100, 100, BTreeMap}
map_insert_seq_bench!{insert_seq_10_000, 10_000, BTreeMap}
map_find_rand_bench!{find_rand_100, 100, BTreeMap}
map_find_rand_bench!{find_rand_10_000, 10_000, BTreeMap}
map_find_seq_bench!{find_seq_100, 100, BTreeMap}
map_find_seq_bench!{find_seq_10_000, 10_000, BTreeMap}
fn bench_iter(b: &mut Bencher, size: i32) {
let mut map = BTreeMap::<i32, i32>::new();
let mut rng = thread_rng();
for _ in 0..size {
map.insert(rng.gen(), rng.gen());
}
b.iter(|| {
for entry in &map {
black_box(entry);
}
});
}
#[bench]
pub fn iter_20(b: &mut Bencher) {
bench_iter(b, 20);
}
#[bench]
pub fn iter_1000(b: &mut Bencher) {
bench_iter(b, 1000);
}
#[bench]
pub fn iter_100000(b: &mut Bencher) {
bench_iter(b, 100000);
}

View File

@ -0,0 +1,11 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
mod map;

View File

@ -0,0 +1,24 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![deny(warnings)]
#![feature(rand)]
#![feature(test)]
extern crate test;
mod btree;
mod linked_list;
mod string;
mod str;
mod slice;
mod vec;
mod vec_deque;

View File

@ -0,0 +1,87 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::collections::LinkedList;
use test::Bencher;
#[bench]
fn bench_collect_into(b: &mut Bencher) {
let v = &[0; 64];
b.iter(|| {
let _: LinkedList<_> = v.iter().cloned().collect();
})
}
#[bench]
fn bench_push_front(b: &mut Bencher) {
let mut m: LinkedList<_> = LinkedList::new();
b.iter(|| {
m.push_front(0);
})
}
#[bench]
fn bench_push_back(b: &mut Bencher) {
let mut m: LinkedList<_> = LinkedList::new();
b.iter(|| {
m.push_back(0);
})
}
#[bench]
fn bench_push_back_pop_back(b: &mut Bencher) {
let mut m: LinkedList<_> = LinkedList::new();
b.iter(|| {
m.push_back(0);
m.pop_back();
})
}
#[bench]
fn bench_push_front_pop_front(b: &mut Bencher) {
let mut m: LinkedList<_> = LinkedList::new();
b.iter(|| {
m.push_front(0);
m.pop_front();
})
}
#[bench]
fn bench_iter(b: &mut Bencher) {
let v = &[0; 128];
let m: LinkedList<_> = v.iter().cloned().collect();
b.iter(|| {
assert!(m.iter().count() == 128);
})
}
#[bench]
fn bench_iter_mut(b: &mut Bencher) {
let v = &[0; 128];
let mut m: LinkedList<_> = v.iter().cloned().collect();
b.iter(|| {
assert!(m.iter_mut().count() == 128);
})
}
#[bench]
fn bench_iter_rev(b: &mut Bencher) {
let v = &[0; 128];
let m: LinkedList<_> = v.iter().cloned().collect();
b.iter(|| {
assert!(m.iter().rev().count() == 128);
})
}
#[bench]
fn bench_iter_mut_rev(b: &mut Bencher) {
let v = &[0; 128];
let mut m: LinkedList<_> = v.iter().cloned().collect();
b.iter(|| {
assert!(m.iter_mut().rev().count() == 128);
})
}

View File

@ -0,0 +1,280 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::{mem, ptr};
use std::__rand::{Rng, thread_rng};
use test::{Bencher, black_box};
#[bench]
fn iterator(b: &mut Bencher) {
// peculiar numbers to stop LLVM from optimising the summation
// out.
let v: Vec<_> = (0..100).map(|i| i ^ (i << 1) ^ (i >> 1)).collect();
b.iter(|| {
let mut sum = 0;
for x in &v {
sum += *x;
}
// sum == 11806, to stop dead code elimination.
if sum == 0 {
panic!()
}
})
}
#[bench]
fn mut_iterator(b: &mut Bencher) {
let mut v = vec![0; 100];
b.iter(|| {
let mut i = 0;
for x in &mut v {
*x = i;
i += 1;
}
})
}
#[bench]
fn concat(b: &mut Bencher) {
let xss: Vec<Vec<i32>> = (0..100).map(|i| (0..i).collect()).collect();
b.iter(|| {
xss.concat();
});
}
#[bench]
fn join(b: &mut Bencher) {
let xss: Vec<Vec<i32>> = (0..100).map(|i| (0..i).collect()).collect();
b.iter(|| xss.join(&0));
}
#[bench]
fn push(b: &mut Bencher) {
let mut vec = Vec::<i32>::new();
b.iter(|| {
vec.push(0);
black_box(&vec);
});
}
#[bench]
fn starts_with_same_vector(b: &mut Bencher) {
let vec: Vec<_> = (0..100).collect();
b.iter(|| vec.starts_with(&vec))
}
#[bench]
fn starts_with_single_element(b: &mut Bencher) {
let vec: Vec<_> = vec![0];
b.iter(|| vec.starts_with(&vec))
}
#[bench]
fn starts_with_diff_one_element_at_end(b: &mut Bencher) {
let vec: Vec<_> = (0..100).collect();
let mut match_vec: Vec<_> = (0..99).collect();
match_vec.push(0);
b.iter(|| vec.starts_with(&match_vec))
}
#[bench]
fn ends_with_same_vector(b: &mut Bencher) {
let vec: Vec<_> = (0..100).collect();
b.iter(|| vec.ends_with(&vec))
}
#[bench]
fn ends_with_single_element(b: &mut Bencher) {
let vec: Vec<_> = vec![0];
b.iter(|| vec.ends_with(&vec))
}
#[bench]
fn ends_with_diff_one_element_at_beginning(b: &mut Bencher) {
let vec: Vec<_> = (0..100).collect();
let mut match_vec: Vec<_> = (0..100).collect();
match_vec[0] = 200;
b.iter(|| vec.starts_with(&match_vec))
}
#[bench]
fn contains_last_element(b: &mut Bencher) {
let vec: Vec<_> = (0..100).collect();
b.iter(|| vec.contains(&99))
}
#[bench]
fn zero_1kb_from_elem(b: &mut Bencher) {
b.iter(|| vec![0u8; 1024]);
}
#[bench]
fn zero_1kb_set_memory(b: &mut Bencher) {
b.iter(|| {
let mut v = Vec::<u8>::with_capacity(1024);
unsafe {
let vp = v.as_mut_ptr();
ptr::write_bytes(vp, 0, 1024);
v.set_len(1024);
}
v
});
}
#[bench]
fn zero_1kb_loop_set(b: &mut Bencher) {
b.iter(|| {
let mut v = Vec::<u8>::with_capacity(1024);
unsafe {
v.set_len(1024);
}
for i in 0..1024 {
v[i] = 0;
}
});
}
#[bench]
fn zero_1kb_mut_iter(b: &mut Bencher) {
b.iter(|| {
let mut v = Vec::<u8>::with_capacity(1024);
unsafe {
v.set_len(1024);
}
for x in &mut v {
*x = 0;
}
v
});
}
#[bench]
fn random_inserts(b: &mut Bencher) {
let mut rng = thread_rng();
b.iter(|| {
let mut v = vec![(0, 0); 30];
for _ in 0..100 {
let l = v.len();
v.insert(rng.gen::<usize>() % (l + 1), (1, 1));
}
})
}
#[bench]
fn random_removes(b: &mut Bencher) {
let mut rng = thread_rng();
b.iter(|| {
let mut v = vec![(0, 0); 130];
for _ in 0..100 {
let l = v.len();
v.remove(rng.gen::<usize>() % l);
}
})
}
fn gen_ascending(len: usize) -> Vec<u64> {
(0..len as u64).collect()
}
fn gen_descending(len: usize) -> Vec<u64> {
(0..len as u64).rev().collect()
}
fn gen_random(len: usize) -> Vec<u64> {
let mut rng = thread_rng();
rng.gen_iter::<u64>().take(len).collect()
}
fn gen_mostly_ascending(len: usize) -> Vec<u64> {
let mut rng = thread_rng();
let mut v = gen_ascending(len);
for _ in (0usize..).take_while(|x| x * x <= len) {
let x = rng.gen::<usize>() % len;
let y = rng.gen::<usize>() % len;
v.swap(x, y);
}
v
}
fn gen_mostly_descending(len: usize) -> Vec<u64> {
let mut rng = thread_rng();
let mut v = gen_descending(len);
for _ in (0usize..).take_while(|x| x * x <= len) {
let x = rng.gen::<usize>() % len;
let y = rng.gen::<usize>() % len;
v.swap(x, y);
}
v
}
fn gen_big_random(len: usize) -> Vec<[u64; 16]> {
let mut rng = thread_rng();
rng.gen_iter().map(|x| [x; 16]).take(len).collect()
}
fn gen_big_ascending(len: usize) -> Vec<[u64; 16]> {
(0..len as u64).map(|x| [x; 16]).take(len).collect()
}
fn gen_big_descending(len: usize) -> Vec<[u64; 16]> {
(0..len as u64).rev().map(|x| [x; 16]).take(len).collect()
}
macro_rules! sort_bench {
($name:ident, $gen:expr, $len:expr) => {
#[bench]
fn $name(b: &mut Bencher) {
b.iter(|| $gen($len).sort());
b.bytes = $len * mem::size_of_val(&$gen(1)[0]) as u64;
}
}
}
sort_bench!(sort_small_random, gen_random, 10);
sort_bench!(sort_small_ascending, gen_ascending, 10);
sort_bench!(sort_small_descending, gen_descending, 10);
sort_bench!(sort_small_big_random, gen_big_random, 10);
sort_bench!(sort_small_big_ascending, gen_big_ascending, 10);
sort_bench!(sort_small_big_descending, gen_big_descending, 10);
sort_bench!(sort_medium_random, gen_random, 100);
sort_bench!(sort_medium_ascending, gen_ascending, 100);
sort_bench!(sort_medium_descending, gen_descending, 100);
sort_bench!(sort_large_random, gen_random, 10000);
sort_bench!(sort_large_ascending, gen_ascending, 10000);
sort_bench!(sort_large_descending, gen_descending, 10000);
sort_bench!(sort_large_mostly_ascending, gen_mostly_ascending, 10000);
sort_bench!(sort_large_mostly_descending, gen_mostly_descending, 10000);
sort_bench!(sort_large_big_random, gen_big_random, 10000);
sort_bench!(sort_large_big_ascending, gen_big_ascending, 10000);
sort_bench!(sort_large_big_descending, gen_big_descending, 10000);
#[bench]
fn sort_large_random_expensive(b: &mut Bencher) {
let len = 10000;
b.iter(|| {
let mut v = gen_random(len);
let mut count = 0;
v.sort_by(|a: &u64, b: &u64| {
count += 1;
if count % 1_000_000_000 == 0 {
panic!("should not happen");
}
(*a as f64).cos().partial_cmp(&(*b as f64).cos()).unwrap()
});
black_box(count);
});
b.bytes = len as u64 * mem::size_of::<u64>() as u64;
}

View File

@ -0,0 +1,298 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use test::{Bencher, black_box};
#[bench]
fn char_iterator(b: &mut Bencher) {
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
b.iter(|| s.chars().count());
}
#[bench]
fn char_iterator_for(b: &mut Bencher) {
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
b.iter(|| {
for ch in s.chars() { black_box(ch); }
});
}
#[bench]
fn char_iterator_ascii(b: &mut Bencher) {
let s = "Mary had a little lamb, Little lamb
Mary had a little lamb, Little lamb
Mary had a little lamb, Little lamb
Mary had a little lamb, Little lamb
Mary had a little lamb, Little lamb
Mary had a little lamb, Little lamb";
b.iter(|| s.chars().count());
}
#[bench]
fn char_iterator_rev(b: &mut Bencher) {
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
b.iter(|| s.chars().rev().count());
}
#[bench]
fn char_iterator_rev_for(b: &mut Bencher) {
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
b.iter(|| {
for ch in s.chars().rev() { black_box(ch); }
});
}
#[bench]
fn char_indicesator(b: &mut Bencher) {
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
let len = s.chars().count();
b.iter(|| assert_eq!(s.char_indices().count(), len));
}
#[bench]
fn char_indicesator_rev(b: &mut Bencher) {
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
let len = s.chars().count();
b.iter(|| assert_eq!(s.char_indices().rev().count(), len));
}
#[bench]
fn split_unicode_ascii(b: &mut Bencher) {
let s = "ประเทศไทย中华Việt Namประเทศไทย中华Việt Nam";
b.iter(|| assert_eq!(s.split('V').count(), 3));
}
#[bench]
fn split_ascii(b: &mut Bencher) {
let s = "Mary had a little lamb, Little lamb, little-lamb.";
let len = s.split(' ').count();
b.iter(|| assert_eq!(s.split(' ').count(), len));
}
#[bench]
fn split_extern_fn(b: &mut Bencher) {
let s = "Mary had a little lamb, Little lamb, little-lamb.";
let len = s.split(' ').count();
fn pred(c: char) -> bool { c == ' ' }
b.iter(|| assert_eq!(s.split(pred).count(), len));
}
#[bench]
fn split_closure(b: &mut Bencher) {
let s = "Mary had a little lamb, Little lamb, little-lamb.";
let len = s.split(' ').count();
b.iter(|| assert_eq!(s.split(|c: char| c == ' ').count(), len));
}
#[bench]
fn split_slice(b: &mut Bencher) {
let s = "Mary had a little lamb, Little lamb, little-lamb.";
let len = s.split(' ').count();
let c: &[char] = &[' '];
b.iter(|| assert_eq!(s.split(c).count(), len));
}
#[bench]
fn bench_join(b: &mut Bencher) {
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
let sep = "";
let v = vec![s, s, s, s, s, s, s, s, s, s];
b.iter(|| {
assert_eq!(v.join(sep).len(), s.len() * 10 + sep.len() * 9);
})
}
#[bench]
fn bench_contains_short_short(b: &mut Bencher) {
let haystack = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
let needle = "sit";
b.iter(|| {
assert!(haystack.contains(needle));
})
}
#[bench]
fn bench_contains_short_long(b: &mut Bencher) {
let haystack = "\
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem sit amet dolor \
ultricies condimentum. Praesent iaculis purus elit, ac malesuada quam malesuada in. Duis sed orci \
eros. Suspendisse sit amet magna mollis, mollis nunc luctus, imperdiet mi. Integer fringilla non \
sem ut lacinia. Fusce varius tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec \
tempus vel, gravida nec quam.
In est dui, tincidunt sed tempus interdum, adipiscing laoreet ante. Etiam tempor, tellus quis \
sagittis interdum, nulla purus mattis sem, quis auctor erat odio ac tellus. In nec nunc sit amet \
diam volutpat molestie at sed ipsum. Vestibulum laoreet consequat vulputate. Integer accumsan \
lorem ac dignissim placerat. Suspendisse convallis faucibus lorem. Aliquam erat volutpat. In vel \
eleifend felis. Sed suscipit nulla lorem, sed mollis est sollicitudin et. Nam fermentum egestas \
interdum. Curabitur ut nisi justo.
Sed sollicitudin ipsum tellus, ut condimentum leo eleifend nec. Cras ut velit ante. Phasellus nec \
mollis odio. Mauris molestie erat in arcu mattis, at aliquet dolor vehicula. Quisque malesuada \
lectus sit amet nisi pretium, a condimentum ipsum porta. Morbi at dapibus diam. Praesent egestas \
est sed risus elementum, eu rutrum metus ultrices. Etiam fermentum consectetur magna, id rutrum \
felis accumsan a. Aliquam ut pellentesque libero. Sed mi nulla, lobortis eu tortor id, suscipit \
ultricies neque. Morbi iaculis sit amet risus at iaculis. Praesent eget ligula quis turpis \
feugiat suscipit vel non arcu. Interdum et malesuada fames ac ante ipsum primis in faucibus. \
Aliquam sit amet placerat lorem.
Cras a lacus vel ante posuere elementum. Nunc est leo, bibendum ut facilisis vel, bibendum at \
mauris. Nullam adipiscing diam vel odio ornare, luctus adipiscing mi luctus. Nulla facilisi. \
Mauris adipiscing bibendum neque, quis adipiscing lectus tempus et. Sed feugiat erat et nisl \
lobortis pharetra. Donec vitae erat enim. Nullam sit amet felis et quam lacinia tincidunt. Aliquam \
suscipit dapibus urna. Sed volutpat urna in magna pulvinar volutpat. Phasellus nec tellus ac diam \
cursus accumsan.
Nam lectus enim, dapibus non nisi tempor, consectetur convallis massa. Maecenas eleifend dictum \
feugiat. Etiam quis mauris vel risus luctus mattis a a nunc. Nullam orci quam, imperdiet id \
vehicula in, porttitor ut nibh. Duis sagittis adipiscing nisl vitae congue. Donec mollis risus eu \
leo suscipit, varius porttitor nulla porta. Pellentesque ut sem nec nisi euismod vehicula. Nulla \
malesuada sollicitudin quam eu fermentum.";
let needle = "english";
b.iter(|| {
assert!(!haystack.contains(needle));
})
}
#[bench]
fn bench_contains_bad_naive(b: &mut Bencher) {
let haystack = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
let needle = "aaaaaaaab";
b.iter(|| {
assert!(!haystack.contains(needle));
})
}
#[bench]
fn bench_contains_equal(b: &mut Bencher) {
let haystack = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
let needle = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
b.iter(|| {
assert!(haystack.contains(needle));
})
}
macro_rules! make_test_inner {
($s:ident, $code:expr, $name:ident, $str:expr) => {
#[bench]
fn $name(bencher: &mut Bencher) {
let mut $s = $str;
black_box(&mut $s);
bencher.iter(|| $code);
}
}
}
macro_rules! make_test {
($name:ident, $s:ident, $code:expr) => {
mod $name {
use test::Bencher;
use test::black_box;
// Short strings: 65 bytes each
make_test_inner!($s, $code, short_ascii,
"Mary had a little lamb, Little lamb Mary had a littl lamb, lamb!");
make_test_inner!($s, $code, short_mixed,
"ศไทย中华Việt Nam; Mary had a little lamb, Little lam!");
make_test_inner!($s, $code, short_pile_of_poo,
"💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩!");
make_test_inner!($s, $code, long_lorem_ipsum,"\
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem sit amet dolor \
ultricies condimentum. Praesent iaculis purus elit, ac malesuada quam malesuada in. Duis sed orci \
eros. Suspendisse sit amet magna mollis, mollis nunc luctus, imperdiet mi. Integer fringilla non \
sem ut lacinia. Fusce varius tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec \
tempus vel, gravida nec quam.
In est dui, tincidunt sed tempus interdum, adipiscing laoreet ante. Etiam tempor, tellus quis \
sagittis interdum, nulla purus mattis sem, quis auctor erat odio ac tellus. In nec nunc sit amet \
diam volutpat molestie at sed ipsum. Vestibulum laoreet consequat vulputate. Integer accumsan \
lorem ac dignissim placerat. Suspendisse convallis faucibus lorem. Aliquam erat volutpat. In vel \
eleifend felis. Sed suscipit nulla lorem, sed mollis est sollicitudin et. Nam fermentum egestas \
interdum. Curabitur ut nisi justo.
Sed sollicitudin ipsum tellus, ut condimentum leo eleifend nec. Cras ut velit ante. Phasellus nec \
mollis odio. Mauris molestie erat in arcu mattis, at aliquet dolor vehicula. Quisque malesuada \
lectus sit amet nisi pretium, a condimentum ipsum porta. Morbi at dapibus diam. Praesent egestas \
est sed risus elementum, eu rutrum metus ultrices. Etiam fermentum consectetur magna, id rutrum \
felis accumsan a. Aliquam ut pellentesque libero. Sed mi nulla, lobortis eu tortor id, suscipit \
ultricies neque. Morbi iaculis sit amet risus at iaculis. Praesent eget ligula quis turpis \
feugiat suscipit vel non arcu. Interdum et malesuada fames ac ante ipsum primis in faucibus. \
Aliquam sit amet placerat lorem.
Cras a lacus vel ante posuere elementum. Nunc est leo, bibendum ut facilisis vel, bibendum at \
mauris. Nullam adipiscing diam vel odio ornare, luctus adipiscing mi luctus. Nulla facilisi. \
Mauris adipiscing bibendum neque, quis adipiscing lectus tempus et. Sed feugiat erat et nisl \
lobortis pharetra. Donec vitae erat enim. Nullam sit amet felis et quam lacinia tincidunt. Aliquam \
suscipit dapibus urna. Sed volutpat urna in magna pulvinar volutpat. Phasellus nec tellus ac diam \
cursus accumsan.
Nam lectus enim, dapibus non nisi tempor, consectetur convallis massa. Maecenas eleifend dictum \
feugiat. Etiam quis mauris vel risus luctus mattis a a nunc. Nullam orci quam, imperdiet id \
vehicula in, porttitor ut nibh. Duis sagittis adipiscing nisl vitae congue. Donec mollis risus eu \
leo suscipit, varius porttitor nulla porta. Pellentesque ut sem nec nisi euismod vehicula. Nulla \
malesuada sollicitudin quam eu fermentum!");
}
}
}
make_test!(chars_count, s, s.chars().count());
make_test!(contains_bang_str, s, s.contains("!"));
make_test!(contains_bang_char, s, s.contains('!'));
make_test!(match_indices_a_str, s, s.match_indices("a").count());
make_test!(split_a_str, s, s.split("a").count());
make_test!(trim_ascii_char, s, {
use std::ascii::AsciiExt;
s.trim_matches(|c: char| c.is_ascii())
});
make_test!(trim_left_ascii_char, s, {
use std::ascii::AsciiExt;
s.trim_left_matches(|c: char| c.is_ascii())
});
make_test!(trim_right_ascii_char, s, {
use std::ascii::AsciiExt;
s.trim_right_matches(|c: char| c.is_ascii())
});
make_test!(find_underscore_char, s, s.find('_'));
make_test!(rfind_underscore_char, s, s.rfind('_'));
make_test!(find_underscore_str, s, s.find("_"));
make_test!(find_zzz_char, s, s.find('\u{1F4A4}'));
make_test!(rfind_zzz_char, s, s.rfind('\u{1F4A4}'));
make_test!(find_zzz_str, s, s.find("\u{1F4A4}"));
make_test!(split_space_char, s, s.split(' ').count());
make_test!(split_terminator_space_char, s, s.split_terminator(' ').count());
make_test!(splitn_space_char, s, s.splitn(10, ' ').count());
make_test!(rsplitn_space_char, s, s.rsplitn(10, ' ').count());
make_test!(split_space_str, s, s.split(" ").count());
make_test!(split_ad_str, s, s.split("ad").count());

View File

@ -0,0 +1,134 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::iter::repeat;
use test::Bencher;
#[bench]
fn bench_with_capacity(b: &mut Bencher) {
b.iter(|| String::with_capacity(100));
}
#[bench]
fn bench_push_str(b: &mut Bencher) {
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
b.iter(|| {
let mut r = String::new();
r.push_str(s);
});
}
const REPETITIONS: u64 = 10_000;
#[bench]
fn bench_push_str_one_byte(b: &mut Bencher) {
b.bytes = REPETITIONS;
b.iter(|| {
let mut r = String::new();
for _ in 0..REPETITIONS {
r.push_str("a")
}
});
}
#[bench]
fn bench_push_char_one_byte(b: &mut Bencher) {
b.bytes = REPETITIONS;
b.iter(|| {
let mut r = String::new();
for _ in 0..REPETITIONS {
r.push('a')
}
});
}
#[bench]
fn bench_push_char_two_bytes(b: &mut Bencher) {
b.bytes = REPETITIONS * 2;
b.iter(|| {
let mut r = String::new();
for _ in 0..REPETITIONS {
r.push('â')
}
});
}
#[bench]
fn from_utf8_lossy_100_ascii(b: &mut Bencher) {
let s = b"Hello there, the quick brown fox jumped over the lazy dog! \
Lorem ipsum dolor sit amet, consectetur. ";
assert_eq!(100, s.len());
b.iter(|| {
let _ = String::from_utf8_lossy(s);
});
}
#[bench]
fn from_utf8_lossy_100_multibyte(b: &mut Bencher) {
let s = "𐌀𐌖𐌋𐌄𐌑𐌉ปรدولة الكويتทศไทย中华𐍅𐌿𐌻𐍆𐌹𐌻𐌰".as_bytes();
assert_eq!(100, s.len());
b.iter(|| {
let _ = String::from_utf8_lossy(s);
});
}
#[bench]
fn from_utf8_lossy_invalid(b: &mut Bencher) {
let s = b"Hello\xC0\x80 There\xE6\x83 Goodbye";
b.iter(|| {
let _ = String::from_utf8_lossy(s);
});
}
#[bench]
fn from_utf8_lossy_100_invalid(b: &mut Bencher) {
let s = repeat(0xf5).take(100).collect::<Vec<_>>();
b.iter(|| {
let _ = String::from_utf8_lossy(&s);
});
}
#[bench]
fn bench_exact_size_shrink_to_fit(b: &mut Bencher) {
let s = "Hello there, the quick brown fox jumped over the lazy dog! \
Lorem ipsum dolor sit amet, consectetur. ";
// ensure our operation produces an exact-size string before we benchmark it
let mut r = String::with_capacity(s.len());
r.push_str(s);
assert_eq!(r.len(), r.capacity());
b.iter(|| {
let mut r = String::with_capacity(s.len());
r.push_str(s);
r.shrink_to_fit();
r
});
}
#[bench]
fn bench_from_str(b: &mut Bencher) {
let s = "Hello there, the quick brown fox jumped over the lazy dog! \
Lorem ipsum dolor sit amet, consectetur. ";
b.iter(|| String::from(s))
}
#[bench]
fn bench_from(b: &mut Bencher) {
let s = "Hello there, the quick brown fox jumped over the lazy dog! \
Lorem ipsum dolor sit amet, consectetur. ";
b.iter(|| String::from(s))
}
#[bench]
fn bench_to_string(b: &mut Bencher) {
let s = "Hello there, the quick brown fox jumped over the lazy dog! \
Lorem ipsum dolor sit amet, consectetur. ";
b.iter(|| s.to_string())
}

View File

@ -0,0 +1,492 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use test::Bencher;
use std::iter::{FromIterator, repeat};
#[bench]
fn bench_new(b: &mut Bencher) {
b.iter(|| {
let v: Vec<u32> = Vec::new();
assert_eq!(v.len(), 0);
assert_eq!(v.capacity(), 0);
})
}
fn do_bench_with_capacity(b: &mut Bencher, src_len: usize) {
b.bytes = src_len as u64;
b.iter(|| {
let v: Vec<u32> = Vec::with_capacity(src_len);
assert_eq!(v.len(), 0);
assert_eq!(v.capacity(), src_len);
})
}
#[bench]
fn bench_with_capacity_0000(b: &mut Bencher) {
do_bench_with_capacity(b, 0)
}
#[bench]
fn bench_with_capacity_0010(b: &mut Bencher) {
do_bench_with_capacity(b, 10)
}
#[bench]
fn bench_with_capacity_0100(b: &mut Bencher) {
do_bench_with_capacity(b, 100)
}
#[bench]
fn bench_with_capacity_1000(b: &mut Bencher) {
do_bench_with_capacity(b, 1000)
}
fn do_bench_from_fn(b: &mut Bencher, src_len: usize) {
b.bytes = src_len as u64;
b.iter(|| {
let dst = (0..src_len).collect::<Vec<_>>();
assert_eq!(dst.len(), src_len);
assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
})
}
#[bench]
fn bench_from_fn_0000(b: &mut Bencher) {
do_bench_from_fn(b, 0)
}
#[bench]
fn bench_from_fn_0010(b: &mut Bencher) {
do_bench_from_fn(b, 10)
}
#[bench]
fn bench_from_fn_0100(b: &mut Bencher) {
do_bench_from_fn(b, 100)
}
#[bench]
fn bench_from_fn_1000(b: &mut Bencher) {
do_bench_from_fn(b, 1000)
}
fn do_bench_from_elem(b: &mut Bencher, src_len: usize) {
b.bytes = src_len as u64;
b.iter(|| {
let dst: Vec<usize> = repeat(5).take(src_len).collect();
assert_eq!(dst.len(), src_len);
assert!(dst.iter().all(|x| *x == 5));
})
}
#[bench]
fn bench_from_elem_0000(b: &mut Bencher) {
do_bench_from_elem(b, 0)
}
#[bench]
fn bench_from_elem_0010(b: &mut Bencher) {
do_bench_from_elem(b, 10)
}
#[bench]
fn bench_from_elem_0100(b: &mut Bencher) {
do_bench_from_elem(b, 100)
}
#[bench]
fn bench_from_elem_1000(b: &mut Bencher) {
do_bench_from_elem(b, 1000)
}
fn do_bench_from_slice(b: &mut Bencher, src_len: usize) {
let src: Vec<_> = FromIterator::from_iter(0..src_len);
b.bytes = src_len as u64;
b.iter(|| {
let dst = src.clone()[..].to_vec();
assert_eq!(dst.len(), src_len);
assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
});
}
#[bench]
fn bench_from_slice_0000(b: &mut Bencher) {
do_bench_from_slice(b, 0)
}
#[bench]
fn bench_from_slice_0010(b: &mut Bencher) {
do_bench_from_slice(b, 10)
}
#[bench]
fn bench_from_slice_0100(b: &mut Bencher) {
do_bench_from_slice(b, 100)
}
#[bench]
fn bench_from_slice_1000(b: &mut Bencher) {
do_bench_from_slice(b, 1000)
}
fn do_bench_from_iter(b: &mut Bencher, src_len: usize) {
let src: Vec<_> = FromIterator::from_iter(0..src_len);
b.bytes = src_len as u64;
b.iter(|| {
let dst: Vec<_> = FromIterator::from_iter(src.clone());
assert_eq!(dst.len(), src_len);
assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
});
}
#[bench]
fn bench_from_iter_0000(b: &mut Bencher) {
do_bench_from_iter(b, 0)
}
#[bench]
fn bench_from_iter_0010(b: &mut Bencher) {
do_bench_from_iter(b, 10)
}
#[bench]
fn bench_from_iter_0100(b: &mut Bencher) {
do_bench_from_iter(b, 100)
}
#[bench]
fn bench_from_iter_1000(b: &mut Bencher) {
do_bench_from_iter(b, 1000)
}
fn do_bench_extend(b: &mut Bencher, dst_len: usize, src_len: usize) {
let dst: Vec<_> = FromIterator::from_iter(0..dst_len);
let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len);
b.bytes = src_len as u64;
b.iter(|| {
let mut dst = dst.clone();
dst.extend(src.clone());
assert_eq!(dst.len(), dst_len + src_len);
assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
});
}
#[bench]
fn bench_extend_0000_0000(b: &mut Bencher) {
do_bench_extend(b, 0, 0)
}
#[bench]
fn bench_extend_0000_0010(b: &mut Bencher) {
do_bench_extend(b, 0, 10)
}
#[bench]
fn bench_extend_0000_0100(b: &mut Bencher) {
do_bench_extend(b, 0, 100)
}
#[bench]
fn bench_extend_0000_1000(b: &mut Bencher) {
do_bench_extend(b, 0, 1000)
}
#[bench]
fn bench_extend_0010_0010(b: &mut Bencher) {
do_bench_extend(b, 10, 10)
}
#[bench]
fn bench_extend_0100_0100(b: &mut Bencher) {
do_bench_extend(b, 100, 100)
}
#[bench]
fn bench_extend_1000_1000(b: &mut Bencher) {
do_bench_extend(b, 1000, 1000)
}
fn do_bench_push_all(b: &mut Bencher, dst_len: usize, src_len: usize) {
let dst: Vec<_> = FromIterator::from_iter(0..dst_len);
let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len);
b.bytes = src_len as u64;
b.iter(|| {
let mut dst = dst.clone();
dst.extend_from_slice(&src);
assert_eq!(dst.len(), dst_len + src_len);
assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
});
}
#[bench]
fn bench_push_all_0000_0000(b: &mut Bencher) {
do_bench_push_all(b, 0, 0)
}
#[bench]
fn bench_push_all_0000_0010(b: &mut Bencher) {
do_bench_push_all(b, 0, 10)
}
#[bench]
fn bench_push_all_0000_0100(b: &mut Bencher) {
do_bench_push_all(b, 0, 100)
}
#[bench]
fn bench_push_all_0000_1000(b: &mut Bencher) {
do_bench_push_all(b, 0, 1000)
}
#[bench]
fn bench_push_all_0010_0010(b: &mut Bencher) {
do_bench_push_all(b, 10, 10)
}
#[bench]
fn bench_push_all_0100_0100(b: &mut Bencher) {
do_bench_push_all(b, 100, 100)
}
#[bench]
fn bench_push_all_1000_1000(b: &mut Bencher) {
do_bench_push_all(b, 1000, 1000)
}
fn do_bench_push_all_move(b: &mut Bencher, dst_len: usize, src_len: usize) {
let dst: Vec<_> = FromIterator::from_iter(0..dst_len);
let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len);
b.bytes = src_len as u64;
b.iter(|| {
let mut dst = dst.clone();
dst.extend(src.clone());
assert_eq!(dst.len(), dst_len + src_len);
assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
});
}
#[bench]
fn bench_push_all_move_0000_0000(b: &mut Bencher) {
do_bench_push_all_move(b, 0, 0)
}
#[bench]
fn bench_push_all_move_0000_0010(b: &mut Bencher) {
do_bench_push_all_move(b, 0, 10)
}
#[bench]
fn bench_push_all_move_0000_0100(b: &mut Bencher) {
do_bench_push_all_move(b, 0, 100)
}
#[bench]
fn bench_push_all_move_0000_1000(b: &mut Bencher) {
do_bench_push_all_move(b, 0, 1000)
}
#[bench]
fn bench_push_all_move_0010_0010(b: &mut Bencher) {
do_bench_push_all_move(b, 10, 10)
}
#[bench]
fn bench_push_all_move_0100_0100(b: &mut Bencher) {
do_bench_push_all_move(b, 100, 100)
}
#[bench]
fn bench_push_all_move_1000_1000(b: &mut Bencher) {
do_bench_push_all_move(b, 1000, 1000)
}
fn do_bench_clone(b: &mut Bencher, src_len: usize) {
let src: Vec<usize> = FromIterator::from_iter(0..src_len);
b.bytes = src_len as u64;
b.iter(|| {
let dst = src.clone();
assert_eq!(dst.len(), src_len);
assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
});
}
#[bench]
fn bench_clone_0000(b: &mut Bencher) {
do_bench_clone(b, 0)
}
#[bench]
fn bench_clone_0010(b: &mut Bencher) {
do_bench_clone(b, 10)
}
#[bench]
fn bench_clone_0100(b: &mut Bencher) {
do_bench_clone(b, 100)
}
#[bench]
fn bench_clone_1000(b: &mut Bencher) {
do_bench_clone(b, 1000)
}
fn do_bench_clone_from(b: &mut Bencher, times: usize, dst_len: usize, src_len: usize) {
let dst: Vec<_> = FromIterator::from_iter(0..src_len);
let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len);
b.bytes = (times * src_len) as u64;
b.iter(|| {
let mut dst = dst.clone();
for _ in 0..times {
dst.clone_from(&src);
assert_eq!(dst.len(), src_len);
assert!(dst.iter().enumerate().all(|(i, x)| dst_len + i == *x));
}
});
}
#[bench]
fn bench_clone_from_01_0000_0000(b: &mut Bencher) {
do_bench_clone_from(b, 1, 0, 0)
}
#[bench]
fn bench_clone_from_01_0000_0010(b: &mut Bencher) {
do_bench_clone_from(b, 1, 0, 10)
}
#[bench]
fn bench_clone_from_01_0000_0100(b: &mut Bencher) {
do_bench_clone_from(b, 1, 0, 100)
}
#[bench]
fn bench_clone_from_01_0000_1000(b: &mut Bencher) {
do_bench_clone_from(b, 1, 0, 1000)
}
#[bench]
fn bench_clone_from_01_0010_0010(b: &mut Bencher) {
do_bench_clone_from(b, 1, 10, 10)
}
#[bench]
fn bench_clone_from_01_0100_0100(b: &mut Bencher) {
do_bench_clone_from(b, 1, 100, 100)
}
#[bench]
fn bench_clone_from_01_1000_1000(b: &mut Bencher) {
do_bench_clone_from(b, 1, 1000, 1000)
}
#[bench]
fn bench_clone_from_01_0010_0100(b: &mut Bencher) {
do_bench_clone_from(b, 1, 10, 100)
}
#[bench]
fn bench_clone_from_01_0100_1000(b: &mut Bencher) {
do_bench_clone_from(b, 1, 100, 1000)
}
#[bench]
fn bench_clone_from_01_0010_0000(b: &mut Bencher) {
do_bench_clone_from(b, 1, 10, 0)
}
#[bench]
fn bench_clone_from_01_0100_0010(b: &mut Bencher) {
do_bench_clone_from(b, 1, 100, 10)
}
#[bench]
fn bench_clone_from_01_1000_0100(b: &mut Bencher) {
do_bench_clone_from(b, 1, 1000, 100)
}
#[bench]
fn bench_clone_from_10_0000_0000(b: &mut Bencher) {
do_bench_clone_from(b, 10, 0, 0)
}
#[bench]
fn bench_clone_from_10_0000_0010(b: &mut Bencher) {
do_bench_clone_from(b, 10, 0, 10)
}
#[bench]
fn bench_clone_from_10_0000_0100(b: &mut Bencher) {
do_bench_clone_from(b, 10, 0, 100)
}
#[bench]
fn bench_clone_from_10_0000_1000(b: &mut Bencher) {
do_bench_clone_from(b, 10, 0, 1000)
}
#[bench]
fn bench_clone_from_10_0010_0010(b: &mut Bencher) {
do_bench_clone_from(b, 10, 10, 10)
}
#[bench]
fn bench_clone_from_10_0100_0100(b: &mut Bencher) {
do_bench_clone_from(b, 10, 100, 100)
}
#[bench]
fn bench_clone_from_10_1000_1000(b: &mut Bencher) {
do_bench_clone_from(b, 10, 1000, 1000)
}
#[bench]
fn bench_clone_from_10_0010_0100(b: &mut Bencher) {
do_bench_clone_from(b, 10, 10, 100)
}
#[bench]
fn bench_clone_from_10_0100_1000(b: &mut Bencher) {
do_bench_clone_from(b, 10, 100, 1000)
}
#[bench]
fn bench_clone_from_10_0010_0000(b: &mut Bencher) {
do_bench_clone_from(b, 10, 10, 0)
}
#[bench]
fn bench_clone_from_10_0100_0010(b: &mut Bencher) {
do_bench_clone_from(b, 10, 100, 10)
}
#[bench]
fn bench_clone_from_10_1000_0100(b: &mut Bencher) {
do_bench_clone_from(b, 10, 1000, 100)
}

View File

@ -0,0 +1,57 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::collections::VecDeque;
use test::{Bencher, black_box};
#[bench]
fn bench_new(b: &mut Bencher) {
b.iter(|| {
let ring: VecDeque<i32> = VecDeque::new();
black_box(ring);
})
}
#[bench]
fn bench_grow_1025(b: &mut Bencher) {
b.iter(|| {
let mut deq = VecDeque::new();
for i in 0..1025 {
deq.push_front(i);
}
black_box(deq);
})
}
#[bench]
fn bench_iter_1000(b: &mut Bencher) {
let ring: VecDeque<_> = (0..1000).collect();
b.iter(|| {
let mut sum = 0;
for &i in &ring {
sum += i;
}
black_box(sum);
})
}
#[bench]
fn bench_mut_iter_1000(b: &mut Bencher) {
let mut ring: VecDeque<_> = (0..1000).collect();
b.iter(|| {
let mut sum = 0;
for i in &mut ring {
sum += *i;
}
black_box(sum);
})
}

View File

@ -606,52 +606,3 @@ fn test_split_off_large_random_sorted() {
assert!(map.into_iter().eq(data.clone().into_iter().filter(|x| x.0 < key)));
assert!(right.into_iter().eq(data.into_iter().filter(|x| x.0 >= key)));
}
mod bench {
use std::collections::BTreeMap;
use std::__rand::{Rng, thread_rng};
use test::{Bencher, black_box};
map_insert_rand_bench!{insert_rand_100, 100, BTreeMap}
map_insert_rand_bench!{insert_rand_10_000, 10_000, BTreeMap}
map_insert_seq_bench!{insert_seq_100, 100, BTreeMap}
map_insert_seq_bench!{insert_seq_10_000, 10_000, BTreeMap}
map_find_rand_bench!{find_rand_100, 100, BTreeMap}
map_find_rand_bench!{find_rand_10_000, 10_000, BTreeMap}
map_find_seq_bench!{find_seq_100, 100, BTreeMap}
map_find_seq_bench!{find_seq_10_000, 10_000, BTreeMap}
fn bench_iter(b: &mut Bencher, size: i32) {
let mut map = BTreeMap::<i32, i32>::new();
let mut rng = thread_rng();
for _ in 0..size {
map.insert(rng.gen(), rng.gen());
}
b.iter(|| {
for entry in &map {
black_box(entry);
}
});
}
#[bench]
pub fn iter_20(b: &mut Bencher) {
bench_iter(b, 20);
}
#[bench]
pub fn iter_1000(b: &mut Bencher) {
bench_iter(b, 1000);
}
#[bench]
pub fn iter_100000(b: &mut Bencher) {
bench_iter(b, 100000);
}
}

View File

@ -35,10 +35,6 @@ extern crate std_unicode;
use std::hash::{Hash, Hasher};
use std::collections::hash_map::DefaultHasher;
#[cfg(test)]
#[macro_use]
mod bench;
mod binary_heap;
mod btree;
mod cow_str;

View File

@ -10,8 +10,6 @@
use std::collections::LinkedList;
use test;
#[test]
fn test_basic() {
let mut m = LinkedList::<Box<_>>::new();
@ -356,81 +354,6 @@ fn test_extend() {
assert!(a.iter().eq(&[1, 2, 3, 4, 5, 6, 7]));
}
#[bench]
fn bench_collect_into(b: &mut test::Bencher) {
let v = &[0; 64];
b.iter(|| {
let _: LinkedList<_> = v.iter().cloned().collect();
})
}
#[bench]
fn bench_push_front(b: &mut test::Bencher) {
let mut m: LinkedList<_> = LinkedList::new();
b.iter(|| {
m.push_front(0);
})
}
#[bench]
fn bench_push_back(b: &mut test::Bencher) {
let mut m: LinkedList<_> = LinkedList::new();
b.iter(|| {
m.push_back(0);
})
}
#[bench]
fn bench_push_back_pop_back(b: &mut test::Bencher) {
let mut m: LinkedList<_> = LinkedList::new();
b.iter(|| {
m.push_back(0);
m.pop_back();
})
}
#[bench]
fn bench_push_front_pop_front(b: &mut test::Bencher) {
let mut m: LinkedList<_> = LinkedList::new();
b.iter(|| {
m.push_front(0);
m.pop_front();
})
}
#[bench]
fn bench_iter(b: &mut test::Bencher) {
let v = &[0; 128];
let m: LinkedList<_> = v.iter().cloned().collect();
b.iter(|| {
assert!(m.iter().count() == 128);
})
}
#[bench]
fn bench_iter_mut(b: &mut test::Bencher) {
let v = &[0; 128];
let mut m: LinkedList<_> = v.iter().cloned().collect();
b.iter(|| {
assert!(m.iter_mut().count() == 128);
})
}
#[bench]
fn bench_iter_rev(b: &mut test::Bencher) {
let v = &[0; 128];
let m: LinkedList<_> = v.iter().cloned().collect();
b.iter(|| {
assert!(m.iter().rev().count() == 128);
})
}
#[bench]
fn bench_iter_mut_rev(b: &mut test::Bencher) {
let v = &[0; 128];
let mut m: LinkedList<_> = v.iter().cloned().collect();
b.iter(|| {
assert!(m.iter_mut().rev().count() == 128);
})
}
#[test]
fn test_contains() {
let mut l = LinkedList::new();

View File

@ -1170,276 +1170,3 @@ fn test_copy_from_slice_dst_shorter() {
let mut dst = [0; 3];
dst.copy_from_slice(&src);
}
mod bench {
use std::{mem, ptr};
use std::__rand::{Rng, thread_rng};
use test::{Bencher, black_box};
#[bench]
fn iterator(b: &mut Bencher) {
// peculiar numbers to stop LLVM from optimising the summation
// out.
let v: Vec<_> = (0..100).map(|i| i ^ (i << 1) ^ (i >> 1)).collect();
b.iter(|| {
let mut sum = 0;
for x in &v {
sum += *x;
}
// sum == 11806, to stop dead code elimination.
if sum == 0 {
panic!()
}
})
}
#[bench]
fn mut_iterator(b: &mut Bencher) {
let mut v = vec![0; 100];
b.iter(|| {
let mut i = 0;
for x in &mut v {
*x = i;
i += 1;
}
})
}
#[bench]
fn concat(b: &mut Bencher) {
let xss: Vec<Vec<i32>> = (0..100).map(|i| (0..i).collect()).collect();
b.iter(|| {
xss.concat();
});
}
#[bench]
fn join(b: &mut Bencher) {
let xss: Vec<Vec<i32>> = (0..100).map(|i| (0..i).collect()).collect();
b.iter(|| xss.join(&0));
}
#[bench]
fn push(b: &mut Bencher) {
let mut vec = Vec::<i32>::new();
b.iter(|| {
vec.push(0);
black_box(&vec);
});
}
#[bench]
fn starts_with_same_vector(b: &mut Bencher) {
let vec: Vec<_> = (0..100).collect();
b.iter(|| vec.starts_with(&vec))
}
#[bench]
fn starts_with_single_element(b: &mut Bencher) {
let vec: Vec<_> = vec![0];
b.iter(|| vec.starts_with(&vec))
}
#[bench]
fn starts_with_diff_one_element_at_end(b: &mut Bencher) {
let vec: Vec<_> = (0..100).collect();
let mut match_vec: Vec<_> = (0..99).collect();
match_vec.push(0);
b.iter(|| vec.starts_with(&match_vec))
}
#[bench]
fn ends_with_same_vector(b: &mut Bencher) {
let vec: Vec<_> = (0..100).collect();
b.iter(|| vec.ends_with(&vec))
}
#[bench]
fn ends_with_single_element(b: &mut Bencher) {
let vec: Vec<_> = vec![0];
b.iter(|| vec.ends_with(&vec))
}
#[bench]
fn ends_with_diff_one_element_at_beginning(b: &mut Bencher) {
let vec: Vec<_> = (0..100).collect();
let mut match_vec: Vec<_> = (0..100).collect();
match_vec[0] = 200;
b.iter(|| vec.starts_with(&match_vec))
}
#[bench]
fn contains_last_element(b: &mut Bencher) {
let vec: Vec<_> = (0..100).collect();
b.iter(|| vec.contains(&99))
}
#[bench]
fn zero_1kb_from_elem(b: &mut Bencher) {
b.iter(|| vec![0u8; 1024]);
}
#[bench]
fn zero_1kb_set_memory(b: &mut Bencher) {
b.iter(|| {
let mut v = Vec::<u8>::with_capacity(1024);
unsafe {
let vp = v.as_mut_ptr();
ptr::write_bytes(vp, 0, 1024);
v.set_len(1024);
}
v
});
}
#[bench]
fn zero_1kb_loop_set(b: &mut Bencher) {
b.iter(|| {
let mut v = Vec::<u8>::with_capacity(1024);
unsafe {
v.set_len(1024);
}
for i in 0..1024 {
v[i] = 0;
}
});
}
#[bench]
fn zero_1kb_mut_iter(b: &mut Bencher) {
b.iter(|| {
let mut v = Vec::<u8>::with_capacity(1024);
unsafe {
v.set_len(1024);
}
for x in &mut v {
*x = 0;
}
v
});
}
#[bench]
fn random_inserts(b: &mut Bencher) {
let mut rng = thread_rng();
b.iter(|| {
let mut v = vec![(0, 0); 30];
for _ in 0..100 {
let l = v.len();
v.insert(rng.gen::<usize>() % (l + 1), (1, 1));
}
})
}
#[bench]
fn random_removes(b: &mut Bencher) {
let mut rng = thread_rng();
b.iter(|| {
let mut v = vec![(0, 0); 130];
for _ in 0..100 {
let l = v.len();
v.remove(rng.gen::<usize>() % l);
}
})
}
fn gen_ascending(len: usize) -> Vec<u64> {
(0..len as u64).collect()
}
fn gen_descending(len: usize) -> Vec<u64> {
(0..len as u64).rev().collect()
}
fn gen_random(len: usize) -> Vec<u64> {
let mut rng = thread_rng();
rng.gen_iter::<u64>().take(len).collect()
}
fn gen_mostly_ascending(len: usize) -> Vec<u64> {
let mut rng = thread_rng();
let mut v = gen_ascending(len);
for _ in (0usize..).take_while(|x| x * x <= len) {
let x = rng.gen::<usize>() % len;
let y = rng.gen::<usize>() % len;
v.swap(x, y);
}
v
}
fn gen_mostly_descending(len: usize) -> Vec<u64> {
let mut rng = thread_rng();
let mut v = gen_descending(len);
for _ in (0usize..).take_while(|x| x * x <= len) {
let x = rng.gen::<usize>() % len;
let y = rng.gen::<usize>() % len;
v.swap(x, y);
}
v
}
fn gen_big_random(len: usize) -> Vec<[u64; 16]> {
let mut rng = thread_rng();
rng.gen_iter().map(|x| [x; 16]).take(len).collect()
}
fn gen_big_ascending(len: usize) -> Vec<[u64; 16]> {
(0..len as u64).map(|x| [x; 16]).take(len).collect()
}
fn gen_big_descending(len: usize) -> Vec<[u64; 16]> {
(0..len as u64).rev().map(|x| [x; 16]).take(len).collect()
}
macro_rules! sort_bench {
($name:ident, $gen:expr, $len:expr) => {
#[bench]
fn $name(b: &mut Bencher) {
b.iter(|| $gen($len).sort());
b.bytes = $len * mem::size_of_val(&$gen(1)[0]) as u64;
}
}
}
sort_bench!(sort_small_random, gen_random, 10);
sort_bench!(sort_small_ascending, gen_ascending, 10);
sort_bench!(sort_small_descending, gen_descending, 10);
sort_bench!(sort_small_big_random, gen_big_random, 10);
sort_bench!(sort_small_big_ascending, gen_big_ascending, 10);
sort_bench!(sort_small_big_descending, gen_big_descending, 10);
sort_bench!(sort_medium_random, gen_random, 100);
sort_bench!(sort_medium_ascending, gen_ascending, 100);
sort_bench!(sort_medium_descending, gen_descending, 100);
sort_bench!(sort_large_random, gen_random, 10000);
sort_bench!(sort_large_ascending, gen_ascending, 10000);
sort_bench!(sort_large_descending, gen_descending, 10000);
sort_bench!(sort_large_mostly_ascending, gen_mostly_ascending, 10000);
sort_bench!(sort_large_mostly_descending, gen_mostly_descending, 10000);
sort_bench!(sort_large_big_random, gen_big_random, 10000);
sort_bench!(sort_large_big_ascending, gen_big_ascending, 10000);
sort_bench!(sort_large_big_descending, gen_big_descending, 10000);
#[bench]
fn sort_large_random_expensive(b: &mut Bencher) {
let len = 10000;
b.iter(|| {
let mut v = gen_random(len);
let mut count = 0;
v.sort_by(|a: &u64, b: &u64| {
count += 1;
if count % 1_000_000_000 == 0 {
panic!("should not happen");
}
(*a as f64).cos().partial_cmp(&(*b as f64).cos()).unwrap()
});
black_box(count);
});
b.bytes = len as u64 * mem::size_of::<u64>() as u64;
}
}

View File

@ -1564,294 +1564,3 @@ fn different_str_pattern_forwarding_lifetimes() {
foo::<&str>("x");
}
mod bench {
use test::{Bencher, black_box};
#[bench]
fn char_iterator(b: &mut Bencher) {
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
b.iter(|| s.chars().count());
}
#[bench]
fn char_iterator_for(b: &mut Bencher) {
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
b.iter(|| {
for ch in s.chars() { black_box(ch); }
});
}
#[bench]
fn char_iterator_ascii(b: &mut Bencher) {
let s = "Mary had a little lamb, Little lamb
Mary had a little lamb, Little lamb
Mary had a little lamb, Little lamb
Mary had a little lamb, Little lamb
Mary had a little lamb, Little lamb
Mary had a little lamb, Little lamb";
b.iter(|| s.chars().count());
}
#[bench]
fn char_iterator_rev(b: &mut Bencher) {
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
b.iter(|| s.chars().rev().count());
}
#[bench]
fn char_iterator_rev_for(b: &mut Bencher) {
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
b.iter(|| {
for ch in s.chars().rev() { black_box(ch); }
});
}
#[bench]
fn char_indicesator(b: &mut Bencher) {
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
let len = s.chars().count();
b.iter(|| assert_eq!(s.char_indices().count(), len));
}
#[bench]
fn char_indicesator_rev(b: &mut Bencher) {
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
let len = s.chars().count();
b.iter(|| assert_eq!(s.char_indices().rev().count(), len));
}
#[bench]
fn split_unicode_ascii(b: &mut Bencher) {
let s = "ประเทศไทย中华Việt Namประเทศไทย中华Việt Nam";
b.iter(|| assert_eq!(s.split('V').count(), 3));
}
#[bench]
fn split_ascii(b: &mut Bencher) {
let s = "Mary had a little lamb, Little lamb, little-lamb.";
let len = s.split(' ').count();
b.iter(|| assert_eq!(s.split(' ').count(), len));
}
#[bench]
fn split_extern_fn(b: &mut Bencher) {
let s = "Mary had a little lamb, Little lamb, little-lamb.";
let len = s.split(' ').count();
fn pred(c: char) -> bool { c == ' ' }
b.iter(|| assert_eq!(s.split(pred).count(), len));
}
#[bench]
fn split_closure(b: &mut Bencher) {
let s = "Mary had a little lamb, Little lamb, little-lamb.";
let len = s.split(' ').count();
b.iter(|| assert_eq!(s.split(|c: char| c == ' ').count(), len));
}
#[bench]
fn split_slice(b: &mut Bencher) {
let s = "Mary had a little lamb, Little lamb, little-lamb.";
let len = s.split(' ').count();
let c: &[char] = &[' '];
b.iter(|| assert_eq!(s.split(c).count(), len));
}
#[bench]
fn bench_join(b: &mut Bencher) {
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
let sep = "";
let v = vec![s, s, s, s, s, s, s, s, s, s];
b.iter(|| {
assert_eq!(v.join(sep).len(), s.len() * 10 + sep.len() * 9);
})
}
#[bench]
fn bench_contains_short_short(b: &mut Bencher) {
let haystack = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
let needle = "sit";
b.iter(|| {
assert!(haystack.contains(needle));
})
}
#[bench]
fn bench_contains_short_long(b: &mut Bencher) {
let haystack = "\
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem sit amet dolor \
ultricies condimentum. Praesent iaculis purus elit, ac malesuada quam malesuada in. Duis sed orci \
eros. Suspendisse sit amet magna mollis, mollis nunc luctus, imperdiet mi. Integer fringilla non \
sem ut lacinia. Fusce varius tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec \
tempus vel, gravida nec quam.
In est dui, tincidunt sed tempus interdum, adipiscing laoreet ante. Etiam tempor, tellus quis \
sagittis interdum, nulla purus mattis sem, quis auctor erat odio ac tellus. In nec nunc sit amet \
diam volutpat molestie at sed ipsum. Vestibulum laoreet consequat vulputate. Integer accumsan \
lorem ac dignissim placerat. Suspendisse convallis faucibus lorem. Aliquam erat volutpat. In vel \
eleifend felis. Sed suscipit nulla lorem, sed mollis est sollicitudin et. Nam fermentum egestas \
interdum. Curabitur ut nisi justo.
Sed sollicitudin ipsum tellus, ut condimentum leo eleifend nec. Cras ut velit ante. Phasellus nec \
mollis odio. Mauris molestie erat in arcu mattis, at aliquet dolor vehicula. Quisque malesuada \
lectus sit amet nisi pretium, a condimentum ipsum porta. Morbi at dapibus diam. Praesent egestas \
est sed risus elementum, eu rutrum metus ultrices. Etiam fermentum consectetur magna, id rutrum \
felis accumsan a. Aliquam ut pellentesque libero. Sed mi nulla, lobortis eu tortor id, suscipit \
ultricies neque. Morbi iaculis sit amet risus at iaculis. Praesent eget ligula quis turpis \
feugiat suscipit vel non arcu. Interdum et malesuada fames ac ante ipsum primis in faucibus. \
Aliquam sit amet placerat lorem.
Cras a lacus vel ante posuere elementum. Nunc est leo, bibendum ut facilisis vel, bibendum at \
mauris. Nullam adipiscing diam vel odio ornare, luctus adipiscing mi luctus. Nulla facilisi. \
Mauris adipiscing bibendum neque, quis adipiscing lectus tempus et. Sed feugiat erat et nisl \
lobortis pharetra. Donec vitae erat enim. Nullam sit amet felis et quam lacinia tincidunt. Aliquam \
suscipit dapibus urna. Sed volutpat urna in magna pulvinar volutpat. Phasellus nec tellus ac diam \
cursus accumsan.
Nam lectus enim, dapibus non nisi tempor, consectetur convallis massa. Maecenas eleifend dictum \
feugiat. Etiam quis mauris vel risus luctus mattis a a nunc. Nullam orci quam, imperdiet id \
vehicula in, porttitor ut nibh. Duis sagittis adipiscing nisl vitae congue. Donec mollis risus eu \
leo suscipit, varius porttitor nulla porta. Pellentesque ut sem nec nisi euismod vehicula. Nulla \
malesuada sollicitudin quam eu fermentum.";
let needle = "english";
b.iter(|| {
assert!(!haystack.contains(needle));
})
}
#[bench]
fn bench_contains_bad_naive(b: &mut Bencher) {
let haystack = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
let needle = "aaaaaaaab";
b.iter(|| {
assert!(!haystack.contains(needle));
})
}
#[bench]
fn bench_contains_equal(b: &mut Bencher) {
let haystack = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
let needle = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
b.iter(|| {
assert!(haystack.contains(needle));
})
}
macro_rules! make_test_inner {
($s:ident, $code:expr, $name:ident, $str:expr) => {
#[bench]
fn $name(bencher: &mut Bencher) {
let mut $s = $str;
black_box(&mut $s);
bencher.iter(|| $code);
}
}
}
macro_rules! make_test {
($name:ident, $s:ident, $code:expr) => {
mod $name {
use test::Bencher;
use test::black_box;
// Short strings: 65 bytes each
make_test_inner!($s, $code, short_ascii,
"Mary had a little lamb, Little lamb Mary had a littl lamb, lamb!");
make_test_inner!($s, $code, short_mixed,
"ศไทย中华Việt Nam; Mary had a little lamb, Little lam!");
make_test_inner!($s, $code, short_pile_of_poo,
"💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩!");
make_test_inner!($s, $code, long_lorem_ipsum,"\
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem sit amet dolor \
ultricies condimentum. Praesent iaculis purus elit, ac malesuada quam malesuada in. Duis sed orci \
eros. Suspendisse sit amet magna mollis, mollis nunc luctus, imperdiet mi. Integer fringilla non \
sem ut lacinia. Fusce varius tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec \
tempus vel, gravida nec quam.
In est dui, tincidunt sed tempus interdum, adipiscing laoreet ante. Etiam tempor, tellus quis \
sagittis interdum, nulla purus mattis sem, quis auctor erat odio ac tellus. In nec nunc sit amet \
diam volutpat molestie at sed ipsum. Vestibulum laoreet consequat vulputate. Integer accumsan \
lorem ac dignissim placerat. Suspendisse convallis faucibus lorem. Aliquam erat volutpat. In vel \
eleifend felis. Sed suscipit nulla lorem, sed mollis est sollicitudin et. Nam fermentum egestas \
interdum. Curabitur ut nisi justo.
Sed sollicitudin ipsum tellus, ut condimentum leo eleifend nec. Cras ut velit ante. Phasellus nec \
mollis odio. Mauris molestie erat in arcu mattis, at aliquet dolor vehicula. Quisque malesuada \
lectus sit amet nisi pretium, a condimentum ipsum porta. Morbi at dapibus diam. Praesent egestas \
est sed risus elementum, eu rutrum metus ultrices. Etiam fermentum consectetur magna, id rutrum \
felis accumsan a. Aliquam ut pellentesque libero. Sed mi nulla, lobortis eu tortor id, suscipit \
ultricies neque. Morbi iaculis sit amet risus at iaculis. Praesent eget ligula quis turpis \
feugiat suscipit vel non arcu. Interdum et malesuada fames ac ante ipsum primis in faucibus. \
Aliquam sit amet placerat lorem.
Cras a lacus vel ante posuere elementum. Nunc est leo, bibendum ut facilisis vel, bibendum at \
mauris. Nullam adipiscing diam vel odio ornare, luctus adipiscing mi luctus. Nulla facilisi. \
Mauris adipiscing bibendum neque, quis adipiscing lectus tempus et. Sed feugiat erat et nisl \
lobortis pharetra. Donec vitae erat enim. Nullam sit amet felis et quam lacinia tincidunt. Aliquam \
suscipit dapibus urna. Sed volutpat urna in magna pulvinar volutpat. Phasellus nec tellus ac diam \
cursus accumsan.
Nam lectus enim, dapibus non nisi tempor, consectetur convallis massa. Maecenas eleifend dictum \
feugiat. Etiam quis mauris vel risus luctus mattis a a nunc. Nullam orci quam, imperdiet id \
vehicula in, porttitor ut nibh. Duis sagittis adipiscing nisl vitae congue. Donec mollis risus eu \
leo suscipit, varius porttitor nulla porta. Pellentesque ut sem nec nisi euismod vehicula. Nulla \
malesuada sollicitudin quam eu fermentum!");
}
}
}
make_test!(chars_count, s, s.chars().count());
make_test!(contains_bang_str, s, s.contains("!"));
make_test!(contains_bang_char, s, s.contains('!'));
make_test!(match_indices_a_str, s, s.match_indices("a").count());
make_test!(split_a_str, s, s.split("a").count());
make_test!(trim_ascii_char, s, {
use std::ascii::AsciiExt;
s.trim_matches(|c: char| c.is_ascii())
});
make_test!(trim_left_ascii_char, s, {
use std::ascii::AsciiExt;
s.trim_left_matches(|c: char| c.is_ascii())
});
make_test!(trim_right_ascii_char, s, {
use std::ascii::AsciiExt;
s.trim_right_matches(|c: char| c.is_ascii())
});
make_test!(find_underscore_char, s, s.find('_'));
make_test!(rfind_underscore_char, s, s.rfind('_'));
make_test!(find_underscore_str, s, s.find("_"));
make_test!(find_zzz_char, s, s.find('\u{1F4A4}'));
make_test!(rfind_zzz_char, s, s.rfind('\u{1F4A4}'));
make_test!(find_zzz_str, s, s.find("\u{1F4A4}"));
make_test!(split_space_char, s, s.split(' ').count());
make_test!(split_terminator_space_char, s, s.split_terminator(' ').count());
make_test!(splitn_space_char, s, s.splitn(10, ' ').count());
make_test!(rsplitn_space_char, s, s.rsplitn(10, ' ').count());
make_test!(split_space_str, s, s.split(" ").count());
make_test!(split_ad_str, s, s.split("ad").count());
}

View File

@ -9,9 +9,6 @@
// except according to those terms.
use std::borrow::Cow;
use std::iter::repeat;
use test::Bencher;
pub trait IntoCow<'a, B: ?Sized> where B: ToOwned {
fn into_cow(self) -> Cow<'a, B>;
@ -436,125 +433,3 @@ fn test_into_boxed_str() {
let ys = xs.into_boxed_str();
assert_eq!(&*ys, "hello my name is bob");
}
#[bench]
fn bench_with_capacity(b: &mut Bencher) {
b.iter(|| String::with_capacity(100));
}
#[bench]
fn bench_push_str(b: &mut Bencher) {
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
b.iter(|| {
let mut r = String::new();
r.push_str(s);
});
}
const REPETITIONS: u64 = 10_000;
#[bench]
fn bench_push_str_one_byte(b: &mut Bencher) {
b.bytes = REPETITIONS;
b.iter(|| {
let mut r = String::new();
for _ in 0..REPETITIONS {
r.push_str("a")
}
});
}
#[bench]
fn bench_push_char_one_byte(b: &mut Bencher) {
b.bytes = REPETITIONS;
b.iter(|| {
let mut r = String::new();
for _ in 0..REPETITIONS {
r.push('a')
}
});
}
#[bench]
fn bench_push_char_two_bytes(b: &mut Bencher) {
b.bytes = REPETITIONS * 2;
b.iter(|| {
let mut r = String::new();
for _ in 0..REPETITIONS {
r.push('â')
}
});
}
#[bench]
fn from_utf8_lossy_100_ascii(b: &mut Bencher) {
let s = b"Hello there, the quick brown fox jumped over the lazy dog! \
Lorem ipsum dolor sit amet, consectetur. ";
assert_eq!(100, s.len());
b.iter(|| {
let _ = String::from_utf8_lossy(s);
});
}
#[bench]
fn from_utf8_lossy_100_multibyte(b: &mut Bencher) {
let s = "𐌀𐌖𐌋𐌄𐌑𐌉ปรدولة الكويتทศไทย中华𐍅𐌿𐌻𐍆𐌹𐌻𐌰".as_bytes();
assert_eq!(100, s.len());
b.iter(|| {
let _ = String::from_utf8_lossy(s);
});
}
#[bench]
fn from_utf8_lossy_invalid(b: &mut Bencher) {
let s = b"Hello\xC0\x80 There\xE6\x83 Goodbye";
b.iter(|| {
let _ = String::from_utf8_lossy(s);
});
}
#[bench]
fn from_utf8_lossy_100_invalid(b: &mut Bencher) {
let s = repeat(0xf5).take(100).collect::<Vec<_>>();
b.iter(|| {
let _ = String::from_utf8_lossy(&s);
});
}
#[bench]
fn bench_exact_size_shrink_to_fit(b: &mut Bencher) {
let s = "Hello there, the quick brown fox jumped over the lazy dog! \
Lorem ipsum dolor sit amet, consectetur. ";
// ensure our operation produces an exact-size string before we benchmark it
let mut r = String::with_capacity(s.len());
r.push_str(s);
assert_eq!(r.len(), r.capacity());
b.iter(|| {
let mut r = String::with_capacity(s.len());
r.push_str(s);
r.shrink_to_fit();
r
});
}
#[bench]
fn bench_from_str(b: &mut Bencher) {
let s = "Hello there, the quick brown fox jumped over the lazy dog! \
Lorem ipsum dolor sit amet, consectetur. ";
b.iter(|| String::from(s))
}
#[bench]
fn bench_from(b: &mut Bencher) {
let s = "Hello there, the quick brown fox jumped over the lazy dog! \
Lorem ipsum dolor sit amet, consectetur. ";
b.iter(|| String::from(s))
}
#[bench]
fn bench_to_string(b: &mut Bencher) {
let s = "Hello there, the quick brown fox jumped over the lazy dog! \
Lorem ipsum dolor sit amet, consectetur. ";
b.iter(|| s.to_string())
}

View File

@ -10,13 +10,10 @@
use std::ascii::AsciiExt;
use std::borrow::Cow;
use std::iter::{FromIterator, repeat};
use std::mem::size_of;
use std::panic;
use std::vec::{Drain, IntoIter};
use test::Bencher;
struct DropCounter<'a> {
count: &'a mut u32,
}
@ -633,483 +630,3 @@ fn test_placement_panic() {
let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { vec.place_back() <- mkpanic(); }));
assert_eq!(vec.len(), 3);
}
#[bench]
fn bench_new(b: &mut Bencher) {
b.iter(|| {
let v: Vec<u32> = Vec::new();
assert_eq!(v.len(), 0);
assert_eq!(v.capacity(), 0);
})
}
fn do_bench_with_capacity(b: &mut Bencher, src_len: usize) {
b.bytes = src_len as u64;
b.iter(|| {
let v: Vec<u32> = Vec::with_capacity(src_len);
assert_eq!(v.len(), 0);
assert_eq!(v.capacity(), src_len);
})
}
#[bench]
fn bench_with_capacity_0000(b: &mut Bencher) {
do_bench_with_capacity(b, 0)
}
#[bench]
fn bench_with_capacity_0010(b: &mut Bencher) {
do_bench_with_capacity(b, 10)
}
#[bench]
fn bench_with_capacity_0100(b: &mut Bencher) {
do_bench_with_capacity(b, 100)
}
#[bench]
fn bench_with_capacity_1000(b: &mut Bencher) {
do_bench_with_capacity(b, 1000)
}
fn do_bench_from_fn(b: &mut Bencher, src_len: usize) {
b.bytes = src_len as u64;
b.iter(|| {
let dst = (0..src_len).collect::<Vec<_>>();
assert_eq!(dst.len(), src_len);
assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
})
}
#[bench]
fn bench_from_fn_0000(b: &mut Bencher) {
do_bench_from_fn(b, 0)
}
#[bench]
fn bench_from_fn_0010(b: &mut Bencher) {
do_bench_from_fn(b, 10)
}
#[bench]
fn bench_from_fn_0100(b: &mut Bencher) {
do_bench_from_fn(b, 100)
}
#[bench]
fn bench_from_fn_1000(b: &mut Bencher) {
do_bench_from_fn(b, 1000)
}
fn do_bench_from_elem(b: &mut Bencher, src_len: usize) {
b.bytes = src_len as u64;
b.iter(|| {
let dst: Vec<usize> = repeat(5).take(src_len).collect();
assert_eq!(dst.len(), src_len);
assert!(dst.iter().all(|x| *x == 5));
})
}
#[bench]
fn bench_from_elem_0000(b: &mut Bencher) {
do_bench_from_elem(b, 0)
}
#[bench]
fn bench_from_elem_0010(b: &mut Bencher) {
do_bench_from_elem(b, 10)
}
#[bench]
fn bench_from_elem_0100(b: &mut Bencher) {
do_bench_from_elem(b, 100)
}
#[bench]
fn bench_from_elem_1000(b: &mut Bencher) {
do_bench_from_elem(b, 1000)
}
fn do_bench_from_slice(b: &mut Bencher, src_len: usize) {
let src: Vec<_> = FromIterator::from_iter(0..src_len);
b.bytes = src_len as u64;
b.iter(|| {
let dst = src.clone()[..].to_vec();
assert_eq!(dst.len(), src_len);
assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
});
}
#[bench]
fn bench_from_slice_0000(b: &mut Bencher) {
do_bench_from_slice(b, 0)
}
#[bench]
fn bench_from_slice_0010(b: &mut Bencher) {
do_bench_from_slice(b, 10)
}
#[bench]
fn bench_from_slice_0100(b: &mut Bencher) {
do_bench_from_slice(b, 100)
}
#[bench]
fn bench_from_slice_1000(b: &mut Bencher) {
do_bench_from_slice(b, 1000)
}
fn do_bench_from_iter(b: &mut Bencher, src_len: usize) {
let src: Vec<_> = FromIterator::from_iter(0..src_len);
b.bytes = src_len as u64;
b.iter(|| {
let dst: Vec<_> = FromIterator::from_iter(src.clone());
assert_eq!(dst.len(), src_len);
assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
});
}
#[bench]
fn bench_from_iter_0000(b: &mut Bencher) {
do_bench_from_iter(b, 0)
}
#[bench]
fn bench_from_iter_0010(b: &mut Bencher) {
do_bench_from_iter(b, 10)
}
#[bench]
fn bench_from_iter_0100(b: &mut Bencher) {
do_bench_from_iter(b, 100)
}
#[bench]
fn bench_from_iter_1000(b: &mut Bencher) {
do_bench_from_iter(b, 1000)
}
fn do_bench_extend(b: &mut Bencher, dst_len: usize, src_len: usize) {
let dst: Vec<_> = FromIterator::from_iter(0..dst_len);
let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len);
b.bytes = src_len as u64;
b.iter(|| {
let mut dst = dst.clone();
dst.extend(src.clone());
assert_eq!(dst.len(), dst_len + src_len);
assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
});
}
#[bench]
fn bench_extend_0000_0000(b: &mut Bencher) {
do_bench_extend(b, 0, 0)
}
#[bench]
fn bench_extend_0000_0010(b: &mut Bencher) {
do_bench_extend(b, 0, 10)
}
#[bench]
fn bench_extend_0000_0100(b: &mut Bencher) {
do_bench_extend(b, 0, 100)
}
#[bench]
fn bench_extend_0000_1000(b: &mut Bencher) {
do_bench_extend(b, 0, 1000)
}
#[bench]
fn bench_extend_0010_0010(b: &mut Bencher) {
do_bench_extend(b, 10, 10)
}
#[bench]
fn bench_extend_0100_0100(b: &mut Bencher) {
do_bench_extend(b, 100, 100)
}
#[bench]
fn bench_extend_1000_1000(b: &mut Bencher) {
do_bench_extend(b, 1000, 1000)
}
fn do_bench_push_all(b: &mut Bencher, dst_len: usize, src_len: usize) {
let dst: Vec<_> = FromIterator::from_iter(0..dst_len);
let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len);
b.bytes = src_len as u64;
b.iter(|| {
let mut dst = dst.clone();
dst.extend_from_slice(&src);
assert_eq!(dst.len(), dst_len + src_len);
assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
});
}
#[bench]
fn bench_push_all_0000_0000(b: &mut Bencher) {
do_bench_push_all(b, 0, 0)
}
#[bench]
fn bench_push_all_0000_0010(b: &mut Bencher) {
do_bench_push_all(b, 0, 10)
}
#[bench]
fn bench_push_all_0000_0100(b: &mut Bencher) {
do_bench_push_all(b, 0, 100)
}
#[bench]
fn bench_push_all_0000_1000(b: &mut Bencher) {
do_bench_push_all(b, 0, 1000)
}
#[bench]
fn bench_push_all_0010_0010(b: &mut Bencher) {
do_bench_push_all(b, 10, 10)
}
#[bench]
fn bench_push_all_0100_0100(b: &mut Bencher) {
do_bench_push_all(b, 100, 100)
}
#[bench]
fn bench_push_all_1000_1000(b: &mut Bencher) {
do_bench_push_all(b, 1000, 1000)
}
fn do_bench_push_all_move(b: &mut Bencher, dst_len: usize, src_len: usize) {
let dst: Vec<_> = FromIterator::from_iter(0..dst_len);
let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len);
b.bytes = src_len as u64;
b.iter(|| {
let mut dst = dst.clone();
dst.extend(src.clone());
assert_eq!(dst.len(), dst_len + src_len);
assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
});
}
#[bench]
fn bench_push_all_move_0000_0000(b: &mut Bencher) {
do_bench_push_all_move(b, 0, 0)
}
#[bench]
fn bench_push_all_move_0000_0010(b: &mut Bencher) {
do_bench_push_all_move(b, 0, 10)
}
#[bench]
fn bench_push_all_move_0000_0100(b: &mut Bencher) {
do_bench_push_all_move(b, 0, 100)
}
#[bench]
fn bench_push_all_move_0000_1000(b: &mut Bencher) {
do_bench_push_all_move(b, 0, 1000)
}
#[bench]
fn bench_push_all_move_0010_0010(b: &mut Bencher) {
do_bench_push_all_move(b, 10, 10)
}
#[bench]
fn bench_push_all_move_0100_0100(b: &mut Bencher) {
do_bench_push_all_move(b, 100, 100)
}
#[bench]
fn bench_push_all_move_1000_1000(b: &mut Bencher) {
do_bench_push_all_move(b, 1000, 1000)
}
fn do_bench_clone(b: &mut Bencher, src_len: usize) {
let src: Vec<usize> = FromIterator::from_iter(0..src_len);
b.bytes = src_len as u64;
b.iter(|| {
let dst = src.clone();
assert_eq!(dst.len(), src_len);
assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
});
}
#[bench]
fn bench_clone_0000(b: &mut Bencher) {
do_bench_clone(b, 0)
}
#[bench]
fn bench_clone_0010(b: &mut Bencher) {
do_bench_clone(b, 10)
}
#[bench]
fn bench_clone_0100(b: &mut Bencher) {
do_bench_clone(b, 100)
}
#[bench]
fn bench_clone_1000(b: &mut Bencher) {
do_bench_clone(b, 1000)
}
fn do_bench_clone_from(b: &mut Bencher, times: usize, dst_len: usize, src_len: usize) {
let dst: Vec<_> = FromIterator::from_iter(0..src_len);
let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len);
b.bytes = (times * src_len) as u64;
b.iter(|| {
let mut dst = dst.clone();
for _ in 0..times {
dst.clone_from(&src);
assert_eq!(dst.len(), src_len);
assert!(dst.iter().enumerate().all(|(i, x)| dst_len + i == *x));
}
});
}
#[bench]
fn bench_clone_from_01_0000_0000(b: &mut Bencher) {
do_bench_clone_from(b, 1, 0, 0)
}
#[bench]
fn bench_clone_from_01_0000_0010(b: &mut Bencher) {
do_bench_clone_from(b, 1, 0, 10)
}
#[bench]
fn bench_clone_from_01_0000_0100(b: &mut Bencher) {
do_bench_clone_from(b, 1, 0, 100)
}
#[bench]
fn bench_clone_from_01_0000_1000(b: &mut Bencher) {
do_bench_clone_from(b, 1, 0, 1000)
}
#[bench]
fn bench_clone_from_01_0010_0010(b: &mut Bencher) {
do_bench_clone_from(b, 1, 10, 10)
}
#[bench]
fn bench_clone_from_01_0100_0100(b: &mut Bencher) {
do_bench_clone_from(b, 1, 100, 100)
}
#[bench]
fn bench_clone_from_01_1000_1000(b: &mut Bencher) {
do_bench_clone_from(b, 1, 1000, 1000)
}
#[bench]
fn bench_clone_from_01_0010_0100(b: &mut Bencher) {
do_bench_clone_from(b, 1, 10, 100)
}
#[bench]
fn bench_clone_from_01_0100_1000(b: &mut Bencher) {
do_bench_clone_from(b, 1, 100, 1000)
}
#[bench]
fn bench_clone_from_01_0010_0000(b: &mut Bencher) {
do_bench_clone_from(b, 1, 10, 0)
}
#[bench]
fn bench_clone_from_01_0100_0010(b: &mut Bencher) {
do_bench_clone_from(b, 1, 100, 10)
}
#[bench]
fn bench_clone_from_01_1000_0100(b: &mut Bencher) {
do_bench_clone_from(b, 1, 1000, 100)
}
#[bench]
fn bench_clone_from_10_0000_0000(b: &mut Bencher) {
do_bench_clone_from(b, 10, 0, 0)
}
#[bench]
fn bench_clone_from_10_0000_0010(b: &mut Bencher) {
do_bench_clone_from(b, 10, 0, 10)
}
#[bench]
fn bench_clone_from_10_0000_0100(b: &mut Bencher) {
do_bench_clone_from(b, 10, 0, 100)
}
#[bench]
fn bench_clone_from_10_0000_1000(b: &mut Bencher) {
do_bench_clone_from(b, 10, 0, 1000)
}
#[bench]
fn bench_clone_from_10_0010_0010(b: &mut Bencher) {
do_bench_clone_from(b, 10, 10, 10)
}
#[bench]
fn bench_clone_from_10_0100_0100(b: &mut Bencher) {
do_bench_clone_from(b, 10, 100, 100)
}
#[bench]
fn bench_clone_from_10_1000_1000(b: &mut Bencher) {
do_bench_clone_from(b, 10, 1000, 1000)
}
#[bench]
fn bench_clone_from_10_0010_0100(b: &mut Bencher) {
do_bench_clone_from(b, 10, 10, 100)
}
#[bench]
fn bench_clone_from_10_0100_1000(b: &mut Bencher) {
do_bench_clone_from(b, 10, 100, 1000)
}
#[bench]
fn bench_clone_from_10_0010_0000(b: &mut Bencher) {
do_bench_clone_from(b, 10, 10, 0)
}
#[bench]
fn bench_clone_from_10_0100_0010(b: &mut Bencher) {
do_bench_clone_from(b, 10, 100, 10)
}
#[bench]
fn bench_clone_from_10_1000_0100(b: &mut Bencher) {
do_bench_clone_from(b, 10, 1000, 100)
}

View File

@ -12,8 +12,6 @@ use std::collections::VecDeque;
use std::fmt::Debug;
use std::collections::vec_deque::Drain;
use test;
use self::Taggy::*;
use self::Taggypar::*;
@ -124,51 +122,6 @@ fn test_index_out_of_bounds() {
deq[3];
}
#[bench]
fn bench_new(b: &mut test::Bencher) {
b.iter(|| {
let ring: VecDeque<i32> = VecDeque::new();
test::black_box(ring);
})
}
#[bench]
fn bench_grow_1025(b: &mut test::Bencher) {
b.iter(|| {
let mut deq = VecDeque::new();
for i in 0..1025 {
deq.push_front(i);
}
test::black_box(deq);
})
}
#[bench]
fn bench_iter_1000(b: &mut test::Bencher) {
let ring: VecDeque<_> = (0..1000).collect();
b.iter(|| {
let mut sum = 0;
for &i in &ring {
sum += i;
}
test::black_box(sum);
})
}
#[bench]
fn bench_mut_iter_1000(b: &mut test::Bencher) {
let mut ring: VecDeque<_> = (0..1000).collect();
b.iter(|| {
let mut sum = 0;
for i in &mut ring {
sum += *i;
}
test::black_box(sum);
})
}
#[derive(Clone, PartialEq, Debug)]
enum Taggy {
One(i32),

View File

@ -14,5 +14,5 @@ name = "coretest"
path = "../libcoretest/lib.rs"
[[bench]]
name = "corebench"
path = "../libcore/bench/lib.rs"
name = "corebenches"
path = "../libcore/benches/lib.rs"

View File

@ -176,46 +176,32 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// Recreate the edges in the graph that are still clean.
let mut clean_work_products = FxHashSet();
let mut dirty_work_products = FxHashSet(); // incomplete; just used to suppress debug output
let mut extra_edges = vec![];
for (source, targets) in &edge_map {
for target in targets {
// If the target is dirty, skip the edge. If this is an edge
// that targets a work-product, we can print the blame
// information now.
if let Some(blame) = dirty_raw_nodes.get(target) {
if let DepNode::WorkProduct(ref wp) = *target {
if tcx.sess.opts.debugging_opts.incremental_info {
if dirty_work_products.insert(wp.clone()) {
// It'd be nice to pretty-print these paths better than just
// using the `Debug` impls, but wev.
println!("incremental: module {:?} is dirty because {:?} \
changed or was removed",
wp,
blame.map_def(|&index| {
Some(directory.def_path_string(tcx, index))
}).unwrap());
}
}
}
continue;
}
// If the source is dirty, the target will be dirty.
assert!(!dirty_raw_nodes.contains_key(source));
// Retrace the source -> target edges to def-ids and then
// create an edge in the graph. Retracing may yield none if
// some of the data happens to have been removed; this ought
// to be impossible unless it is dirty, so we can unwrap.
let source_node = retraced.map(source).unwrap();
let target_node = retraced.map(target).unwrap();
let _task = tcx.dep_graph.in_task(target_node);
tcx.dep_graph.read(source_node);
if let DepNode::WorkProduct(ref wp) = *target {
clean_work_products.insert(wp.clone());
}
process_edges(tcx, source, target, &edge_map, &directory, &retraced, &dirty_raw_nodes,
&mut clean_work_products, &mut dirty_work_products, &mut extra_edges);
}
}
// Subtle. Sometimes we have intermediate nodes that we can't recreate in the new graph.
// This is pretty unusual but it arises in a scenario like this:
//
// Hir(X) -> Foo(Y) -> Bar
//
// Note that the `Hir(Y)` is not an input to `Foo(Y)` -- this
// almost never happens, but can happen in some obscure
// scenarios. In that case, if `Y` is removed, then we can't
// recreate `Foo(Y)` (the def-id `Y` no longer exists); what we do
// then is to push the edge `Hir(X) -> Bar` onto `extra_edges`
// (along with any other targets of `Foo(Y)`). We will then add
// the edge from `Hir(X)` to `Bar` (or, if `Bar` itself cannot be
// recreated, to the targets of `Bar`).
while let Some((source, target)) = extra_edges.pop() {
process_edges(tcx, source, target, &edge_map, &directory, &retraced, &dirty_raw_nodes,
&mut clean_work_products, &mut dirty_work_products, &mut extra_edges);
}
// Add in work-products that are still clean, and delete those that are
// dirty.
reconcile_work_products(tcx, work_products, &clean_work_products);
@ -393,3 +379,66 @@ fn load_prev_metadata_hashes(tcx: TyCtxt,
serialized_hashes.index_map.len());
}
fn process_edges<'a, 'tcx, 'edges>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
source: &'edges DepNode<DefPathIndex>,
target: &'edges DepNode<DefPathIndex>,
edges: &'edges FxHashMap<DepNode<DefPathIndex>, Vec<DepNode<DefPathIndex>>>,
directory: &DefIdDirectory,
retraced: &RetracedDefIdDirectory,
dirty_raw_nodes: &DirtyNodes,
clean_work_products: &mut FxHashSet<Arc<WorkProductId>>,
dirty_work_products: &mut FxHashSet<Arc<WorkProductId>>,
extra_edges: &mut Vec<(&'edges DepNode<DefPathIndex>, &'edges DepNode<DefPathIndex>)>)
{
// If the target is dirty, skip the edge. If this is an edge
// that targets a work-product, we can print the blame
// information now.
if let Some(blame) = dirty_raw_nodes.get(target) {
if let DepNode::WorkProduct(ref wp) = *target {
if tcx.sess.opts.debugging_opts.incremental_info {
if dirty_work_products.insert(wp.clone()) {
// It'd be nice to pretty-print these paths better than just
// using the `Debug` impls, but wev.
println!("incremental: module {:?} is dirty because {:?} \
changed or was removed",
wp,
blame.map_def(|&index| {
Some(directory.def_path_string(tcx, index))
}).unwrap());
}
}
}
return;
}
// If the source is dirty, the target will be dirty.
assert!(!dirty_raw_nodes.contains_key(source));
// Retrace the source -> target edges to def-ids and then create
// an edge in the graph. Retracing may yield none if some of the
// data happens to have been removed.
if let Some(source_node) = retraced.map(source) {
if let Some(target_node) = retraced.map(target) {
let _task = tcx.dep_graph.in_task(target_node);
tcx.dep_graph.read(source_node);
if let DepNode::WorkProduct(ref wp) = *target {
clean_work_products.insert(wp.clone());
}
} else {
// As discussed in `decode_dep_graph` above, sometimes the
// target cannot be recreated again, in which case we add
// edges to go from `source` to the targets of `target`.
extra_edges.extend(
edges[target].iter().map(|t| (source, t)));
}
} else {
// It's also possible that the source can't be created! But we
// can ignore such cases, because (a) if `source` is a HIR
// node, it would be considered dirty; and (b) in other cases,
// there must be some input to this node that is clean, and so
// we'll re-create the edges over in the case where target is
// undefined.
}
}

View File

@ -339,6 +339,7 @@ struct ImproperCTypesVisitor<'a, 'tcx: 'a> {
enum FfiResult {
FfiSafe,
FfiPhantom,
FfiUnsafe(&'static str),
FfiBadStruct(DefId, &'static str),
FfiBadUnion(DefId, &'static str),
@ -383,8 +384,11 @@ fn is_repr_nullable_ptr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
/// Check if the given type is "ffi-safe" (has a stable, well-defined
/// representation which can be exported to C code).
fn check_type_for_ffi(&self, cache: &mut FxHashSet<Ty<'tcx>>, ty: Ty<'tcx>) -> FfiResult {
fn check_type_for_ffi(&self,
cache: &mut FxHashSet<Ty<'tcx>>,
ty: Ty<'tcx>) -> FfiResult {
use self::FfiResult::*;
let cx = self.cx.tcx;
// Protect against infinite recursion, for example
@ -397,6 +401,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
match ty.sty {
ty::TyAdt(def, substs) => {
if def.is_phantom_data() {
return FfiPhantom;
}
match def.adt_kind() {
AdtKind::Struct => {
if !cx.lookup_repr_hints(def.did).contains(&attr::ReprExtern) {
@ -405,18 +412,22 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
consider adding a #[repr(C)] attribute to the type");
}
// We can't completely trust repr(C) markings; make sure the
// fields are actually safe.
if def.struct_variant().fields.is_empty() {
return FfiUnsafe("found zero-size struct in foreign module, consider \
adding a member to this struct");
}
// We can't completely trust repr(C) markings; make sure the
// fields are actually safe.
let mut all_phantom = true;
for field in &def.struct_variant().fields {
let field_ty = cx.normalize_associated_type(&field.ty(cx, substs));
let r = self.check_type_for_ffi(cache, field_ty);
match r {
FfiSafe => {}
FfiSafe => {
all_phantom = false;
}
FfiPhantom => {}
FfiBadStruct(..) | FfiBadUnion(..) | FfiBadEnum(..) => {
return r;
}
@ -425,7 +436,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
}
}
}
FfiSafe
if all_phantom { FfiPhantom } else { FfiSafe }
}
AdtKind::Union => {
if !cx.lookup_repr_hints(def.did).contains(&attr::ReprExtern) {
@ -434,11 +446,20 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
consider adding a #[repr(C)] attribute to the type");
}
if def.struct_variant().fields.is_empty() {
return FfiUnsafe("found zero-size union in foreign module, consider \
adding a member to this union");
}
let mut all_phantom = true;
for field in &def.struct_variant().fields {
let field_ty = cx.normalize_associated_type(&field.ty(cx, substs));
let r = self.check_type_for_ffi(cache, field_ty);
match r {
FfiSafe => {}
FfiSafe => {
all_phantom = false;
}
FfiPhantom => {}
FfiBadStruct(..) | FfiBadUnion(..) | FfiBadEnum(..) => {
return r;
}
@ -447,7 +468,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
}
}
}
FfiSafe
if all_phantom { FfiPhantom } else { FfiSafe }
}
AdtKind::Enum => {
if def.variants.is_empty() {
@ -498,6 +520,10 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
FfiBadStruct(..) | FfiBadUnion(..) | FfiBadEnum(..) => {
return r;
}
FfiPhantom => {
return FfiBadEnum(def.did,
"Found phantom data in enum variant");
}
FfiUnsafe(s) => {
return FfiBadEnum(def.did, s);
}
@ -591,6 +617,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
match self.check_type_for_ffi(&mut FxHashSet(), ty) {
FfiResult::FfiSafe => {}
FfiResult::FfiPhantom => {
self.cx.span_lint(IMPROPER_CTYPES,
sp,
&format!("found zero-sized type composed only \
of phantom-data in a foreign-function."));
}
FfiResult::FfiUnsafe(s) => {
self.cx.span_lint(IMPROPER_CTYPES, sp, s);
}

View File

@ -1369,14 +1369,14 @@ extern "C" {
pub fn LLVMRustDIBuilderCreateBasicType(Builder: DIBuilderRef,
Name: *const c_char,
SizeInBits: u64,
AlignInBits: u64,
AlignInBits: u32,
Encoding: c_uint)
-> DIBasicType;
pub fn LLVMRustDIBuilderCreatePointerType(Builder: DIBuilderRef,
PointeeTy: DIType,
SizeInBits: u64,
AlignInBits: u64,
AlignInBits: u32,
Name: *const c_char)
-> DIDerivedType;
@ -1386,7 +1386,7 @@ extern "C" {
File: DIFile,
LineNumber: c_uint,
SizeInBits: u64,
AlignInBits: u64,
AlignInBits: u32,
Flags: DIFlags,
DerivedFrom: DIType,
Elements: DIArray,
@ -1401,7 +1401,7 @@ extern "C" {
File: DIFile,
LineNo: c_uint,
SizeInBits: u64,
AlignInBits: u64,
AlignInBits: u32,
OffsetInBits: u64,
Flags: DIFlags,
Ty: DIType)
@ -1429,7 +1429,7 @@ extern "C" {
isLocalToUnit: bool,
Val: ValueRef,
Decl: DIDescriptor,
AlignInBits: u64)
AlignInBits: u32)
-> DIGlobalVariable;
pub fn LLVMRustDIBuilderCreateVariable(Builder: DIBuilderRef,
@ -1442,19 +1442,19 @@ extern "C" {
AlwaysPreserve: bool,
Flags: DIFlags,
ArgNo: c_uint,
AlignInBits: u64)
AlignInBits: u32)
-> DIVariable;
pub fn LLVMRustDIBuilderCreateArrayType(Builder: DIBuilderRef,
Size: u64,
AlignInBits: u64,
AlignInBits: u32,
Ty: DIType,
Subscripts: DIArray)
-> DIType;
pub fn LLVMRustDIBuilderCreateVectorType(Builder: DIBuilderRef,
Size: u64,
AlignInBits: u64,
AlignInBits: u32,
Ty: DIType,
Subscripts: DIArray)
-> DIType;
@ -1489,7 +1489,7 @@ extern "C" {
File: DIFile,
LineNumber: c_uint,
SizeInBits: u64,
AlignInBits: u64,
AlignInBits: u32,
Elements: DIArray,
ClassType: DIType)
-> DIType;
@ -1500,7 +1500,7 @@ extern "C" {
File: DIFile,
LineNumber: c_uint,
SizeInBits: u64,
AlignInBits: u64,
AlignInBits: u32,
Flags: DIFlags,
Elements: DIArray,
RunTimeLang: c_uint,

View File

@ -27,6 +27,7 @@ use errors::emitter::Emitter;
use syntax_pos::MultiSpan;
use context::{is_pie_binary, get_reloc_model};
use std::cmp;
use std::ffi::CString;
use std::fs;
use std::path::{Path, PathBuf};
@ -754,10 +755,13 @@ pub fn run_passes(sess: &Session,
}
// Process the work items, optionally using worker threads.
// NOTE: This code is not really adapted to incremental compilation where
// the compiler decides the number of codegen units (and will
// potentially create hundreds of them).
let num_workers = work_items.len() - 1;
// NOTE: We are hardcoding a limit of worker threads for now. With
// incremental compilation we can run into situations where we would
// open hundreds of threads otherwise -- which can make things slower
// if things don't fit into memory anymore, or can cause the compiler
// to crash because of too many open file handles. See #39280 for
// some discussion on how to improve this in the future.
let num_workers = cmp::min(work_items.len() - 1, 32);
if num_workers <= 1 {
run_work_singlethreaded(sess, &trans.exported_symbols, work_items);
} else {

View File

@ -1783,7 +1783,7 @@ pub fn create_global_var_metadata(cx: &CrateContext,
is_local_to_unit,
global,
ptr::null_mut(),
global_align as u64,
global_align,
);
}
}

View File

@ -464,7 +464,7 @@ pub fn declare_local<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
cx.sess().opts.optimize != config::OptLevel::No,
DIFlags::FlagZero,
argument_index,
align as u64,
align,
)
};
source_loc::set_debug_location(bcx,

View File

@ -24,6 +24,8 @@ use type_::Type;
use syntax_pos::{self, Span};
use syntax::ast;
use std::ops;
pub fn is_node_local_to_unit(cx: &CrateContext, node_id: ast::NodeId) -> bool
{
// The is_local_to_unit flag indicates whether a function is local to the
@ -49,12 +51,13 @@ pub fn span_start(cx: &CrateContext, span: Span) -> syntax_pos::Loc {
cx.sess().codemap().lookup_char_pos(span.lo)
}
pub fn size_and_align_of(cx: &CrateContext, llvm_type: Type) -> (u64, u64) {
(machine::llsize_of_alloc(cx, llvm_type), machine::llalign_of_min(cx, llvm_type) as u64)
pub fn size_and_align_of(cx: &CrateContext, llvm_type: Type) -> (u64, u32) {
(machine::llsize_of_alloc(cx, llvm_type), machine::llalign_of_min(cx, llvm_type))
}
pub fn bytes_to_bits(bytes: u64) -> u64 {
bytes * 8
pub fn bytes_to_bits<T>(bytes: T) -> T
where T: ops::Mul<Output=T> + From<u8> {
bytes * 8u8.into()
}
#[inline]

View File

@ -35,6 +35,7 @@ use std::fmt::{self, Write};
use std::slice;
use std::str;
use syntax::feature_gate::UnstableFeatures;
use syntax::codemap::Span;
use html::render::derive_id;
use html::toc::TocBuilder;
@ -424,7 +425,7 @@ pub fn render(w: &mut fmt::Formatter,
}
}
pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, start_line: usize) {
pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Span) {
extern fn block(_ob: *mut hoedown_buffer,
text: *const hoedown_buffer,
lang: *const hoedown_buffer,
@ -449,11 +450,12 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, start_line:
});
let text = lines.collect::<Vec<&str>>().join("\n");
let line = tests.get_line() + line;
let filename = tests.get_filename();
tests.add_test(text.to_owned(),
block_info.should_panic, block_info.no_run,
block_info.ignore, block_info.test_harness,
block_info.compile_fail, block_info.error_codes,
line);
line, filename);
}
}
@ -474,7 +476,7 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, start_line:
}
}
tests.set_line(start_line);
tests.set_position(position);
unsafe {
let ob = hoedown_buffer_new(DEF_OUNIT);
let renderer = hoedown_html_renderer_new(0, 0);

View File

@ -18,6 +18,7 @@ use getopts;
use testing;
use rustc::session::search_paths::SearchPaths;
use rustc::session::config::Externs;
use syntax::codemap::DUMMY_SP;
use externalfiles::{ExternalHtml, LoadStringError, load_string};
@ -154,9 +155,8 @@ pub fn test(input: &str, cfgs: Vec<String>, libs: SearchPaths, externs: Externs,
let mut opts = TestOptions::default();
opts.no_crate_inject = true;
let mut collector = Collector::new(input.to_string(), cfgs, libs, externs,
true, opts, maybe_sysroot, "input".to_string(),
None);
find_testable_code(&input_str, &mut collector, 0);
true, opts, maybe_sysroot, None);
find_testable_code(&input_str, &mut collector, DUMMY_SP);
test_args.insert(0, "rustdoctest".to_string());
testing::test_main(&test_args, collector.tests);
0

View File

@ -37,7 +37,7 @@ use rustc_trans::back::link;
use syntax::ast;
use syntax::codemap::CodeMap;
use syntax::feature_gate::UnstableFeatures;
use syntax_pos::{BytePos, DUMMY_SP, Pos};
use syntax_pos::{BytePos, DUMMY_SP, Pos, Span};
use errors;
use errors::emitter::ColorConfig;
@ -97,7 +97,6 @@ pub fn run(input: &str,
link::find_crate_name(None, &hir_forest.krate().attrs, &input)
});
let opts = scrape_test_config(hir_forest.krate());
let filename = input_path.to_str().unwrap_or("").to_owned();
let mut collector = Collector::new(crate_name,
cfgs,
libs,
@ -105,7 +104,6 @@ pub fn run(input: &str,
false,
opts,
maybe_sysroot,
filename,
Some(codemap));
{
@ -391,15 +389,14 @@ pub struct Collector {
cratename: String,
opts: TestOptions,
maybe_sysroot: Option<PathBuf>,
filename: String,
start_line: usize,
position: Span,
codemap: Option<Rc<CodeMap>>,
}
impl Collector {
pub fn new(cratename: String, cfgs: Vec<String>, libs: SearchPaths, externs: Externs,
use_headers: bool, opts: TestOptions, maybe_sysroot: Option<PathBuf>,
filename: String, codemap: Option<Rc<CodeMap>>) -> Collector {
codemap: Option<Rc<CodeMap>>) -> Collector {
Collector {
tests: Vec::new(),
names: Vec::new(),
@ -412,8 +409,7 @@ impl Collector {
cratename: cratename,
opts: opts,
maybe_sysroot: maybe_sysroot,
filename: filename,
start_line: 0,
position: DUMMY_SP,
codemap: codemap,
}
}
@ -421,8 +417,8 @@ impl Collector {
pub fn add_test(&mut self, test: String,
should_panic: bool, no_run: bool, should_ignore: bool,
as_test_harness: bool, compile_fail: bool, error_codes: Vec<String>,
line: usize) {
let name = format!("{} - line {}", self.filename, line);
line: usize, filename: String) {
let name = format!("{} - line {}", filename, line);
self.cnt += 1;
let cfgs = self.cfgs.clone();
let libs = self.libs.clone();
@ -467,16 +463,25 @@ impl Collector {
}
pub fn get_line(&self) -> usize {
if let Some(ref codemap) = self.codemap{
let line = codemap.lookup_char_pos(BytePos(self.start_line as u32)).line;
if let Some(ref codemap) = self.codemap {
let line = self.position.lo.to_usize();
let line = codemap.lookup_char_pos(BytePos(line as u32)).line;
if line > 0 { line - 1 } else { line }
} else {
self.start_line
0
}
}
pub fn set_line(&mut self, start_line: usize) {
self.start_line = start_line;
pub fn set_position(&mut self, position: Span) {
self.position = position;
}
pub fn get_filename(&self) -> String {
if let Some(ref codemap) = self.codemap {
codemap.span_to_filename(self.position)
} else {
"<input>".to_owned()
}
}
pub fn register_header(&mut self, name: &str, level: u32) {
@ -520,7 +525,7 @@ impl<'a, 'hir> HirCollector<'a, 'hir> {
if let Some(doc) = attrs.doc_value() {
self.collector.cnt = 0;
markdown::find_testable_code(doc, self.collector,
attrs.span.unwrap_or(DUMMY_SP).lo.to_usize());
attrs.span.unwrap_or(DUMMY_SP));
}
nested(self);

View File

@ -844,9 +844,9 @@ impl Child {
/// guaranteed to repeatedly return a successful exit status so long as the
/// child has already exited.
///
/// If the child has exited, then `Ok(status)` is returned. If the exit
/// status is not available at this time then an error is returned with the
/// error kind `WouldBlock`. If an error occurs, then that error is returned.
/// If the child has exited, then `Ok(Some(status))` is returned. If the
/// exit status is not available at this time then `Ok(None)` is returned.
/// If an error occurs, then that error is returned.
///
/// Note that unlike `wait`, this function will not attempt to drop stdin.
///
@ -857,14 +857,13 @@ impl Child {
/// ```no_run
/// #![feature(process_try_wait)]
///
/// use std::io;
/// use std::process::Command;
///
/// let mut child = Command::new("ls").spawn().unwrap();
///
/// match child.try_wait() {
/// Ok(status) => println!("exited with: {}", status),
/// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
/// Ok(Some(status)) => println!("exited with: {}", status),
/// Ok(None) => {
/// println!("status not ready yet, let's really wait");
/// let res = child.wait();
/// println!("result: {:?}", res);
@ -873,8 +872,8 @@ impl Child {
/// }
/// ```
#[unstable(feature = "process_try_wait", issue = "38903")]
pub fn try_wait(&mut self) -> io::Result<ExitStatus> {
self.handle.try_wait().map(ExitStatus)
pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
Ok(self.handle.try_wait()?.map(ExitStatus))
}
/// Simultaneously waits for the child to exit and collect all remaining

View File

@ -502,17 +502,17 @@ impl Process {
Ok(ExitStatus(status as i32))
}
pub fn try_wait(&mut self) -> io::Result<ExitStatus> {
pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
if let Some(status) = self.status {
return Ok(status)
return Ok(Some(status))
}
let mut status = 0;
let pid = cvt(syscall::waitpid(self.pid, &mut status, syscall::WNOHANG))?;
if pid == 0 {
Err(io::Error::from_raw_os_error(syscall::EWOULDBLOCK))
Ok(None)
} else {
self.status = Some(ExitStatus(status as i32));
Ok(ExitStatus(status as i32))
Ok(Some(ExitStatus(status as i32)))
}
}
}

View File

@ -165,7 +165,7 @@ impl Process {
Ok(ExitStatus::new(proc_info.rec.return_code))
}
pub fn try_wait(&mut self) -> io::Result<ExitStatus> {
pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
use default::Default;
use sys::process::magenta::*;
@ -179,7 +179,7 @@ impl Process {
match status {
0 => { }, // Success
x if x == ERR_TIMED_OUT => {
return Err(io::Error::from(io::ErrorKind::WouldBlock));
return Ok(None);
},
_ => { panic!("Failed to wait on process handle: {}", status); },
}
@ -192,7 +192,7 @@ impl Process {
return Err(io::Error::new(io::ErrorKind::InvalidData,
"Failed to get exit status of process"));
}
Ok(ExitStatus::new(proc_info.rec.return_code))
Ok(Some(ExitStatus::new(proc_info.rec.return_code)))
}
}

View File

@ -249,19 +249,19 @@ impl Process {
Ok(ExitStatus::new(status))
}
pub fn try_wait(&mut self) -> io::Result<ExitStatus> {
pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
if let Some(status) = self.status {
return Ok(status)
return Ok(Some(status))
}
let mut status = 0 as c_int;
let pid = cvt(unsafe {
libc::waitpid(self.pid, &mut status, libc::WNOHANG)
})?;
if pid == 0 {
Err(io::Error::from_raw_os_error(libc::EWOULDBLOCK))
Ok(None)
} else {
self.status = Some(ExitStatus::new(status));
Ok(ExitStatus::new(status))
Ok(Some(ExitStatus::new(status)))
}
}
}

View File

@ -340,18 +340,18 @@ impl Process {
}
}
pub fn try_wait(&mut self) -> io::Result<ExitStatus> {
pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
unsafe {
match c::WaitForSingleObject(self.handle.raw(), 0) {
c::WAIT_OBJECT_0 => {}
c::WAIT_TIMEOUT => {
return Err(io::Error::from_raw_os_error(c::WSAEWOULDBLOCK))
return Ok(None);
}
_ => return Err(io::Error::last_os_error()),
}
let mut status = 0;
cvt(c::GetExitCodeProcess(self.handle.raw(), &mut status))?;
Ok(ExitStatus(status))
Ok(Some(ExitStatus(status)))
}
}

View File

@ -60,11 +60,95 @@
//! by two zero-length breaks. The algorithm will try its best to fit it on a
//! line (which it can't) and so naturally place the content on its own line to
//! avoid combining it with other lines and making matters even worse.
//!
//! # Explanation
//!
//! In case you do not have the paper, here is an explanation of what's going
//! on.
//!
//! There is a stream of input tokens flowing through this printer.
//!
//! The printer buffers up to 3N tokens inside itself, where N is linewidth.
//! Yes, linewidth is chars and tokens are multi-char, but in the worst
//! case every token worth buffering is 1 char long, so it's ok.
//!
//! Tokens are String, Break, and Begin/End to delimit blocks.
//!
//! Begin tokens can carry an offset, saying "how far to indent when you break
//! inside here", as well as a flag indicating "consistent" or "inconsistent"
//! breaking. Consistent breaking means that after the first break, no attempt
//! will be made to flow subsequent breaks together onto lines. Inconsistent
//! is the opposite. Inconsistent breaking example would be, say:
//!
//! ```
//! foo(hello, there, good, friends)
//! ```
//!
//! breaking inconsistently to become
//!
//! ```
//! foo(hello, there
//! good, friends);
//! ```
//!
//! whereas a consistent breaking would yield:
//!
//! ```
//! foo(hello,
//! there
//! good,
//! friends);
//! ```
//!
//! That is, in the consistent-break blocks we value vertical alignment
//! more than the ability to cram stuff onto a line. But in all cases if it
//! can make a block a one-liner, it'll do so.
//!
//! Carrying on with high-level logic:
//!
//! The buffered tokens go through a ring-buffer, 'tokens'. The 'left' and
//! 'right' indices denote the active portion of the ring buffer as well as
//! describing hypothetical points-in-the-infinite-stream at most 3N tokens
//! apart (i.e. "not wrapped to ring-buffer boundaries"). The paper will switch
//! between using 'left' and 'right' terms to denote the wrapped-to-ring-buffer
//! and point-in-infinite-stream senses freely.
//!
//! There is a parallel ring buffer, 'size', that holds the calculated size of
//! each token. Why calculated? Because for Begin/End pairs, the "size"
//! includes everything between the pair. That is, the "size" of Begin is
//! actually the sum of the sizes of everything between Begin and the paired
//! End that follows. Since that is arbitrarily far in the future, 'size' is
//! being rewritten regularly while the printer runs; in fact most of the
//! machinery is here to work out 'size' entries on the fly (and give up when
//! they're so obviously over-long that "infinity" is a good enough
//! approximation for purposes of line breaking).
//!
//! The "input side" of the printer is managed as an abstract process called
//! SCAN, which uses 'scan_stack', to manage calculating 'size'. SCAN is, in
//! other words, the process of calculating 'size' entries.
//!
//! The "output side" of the printer is managed by an abstract process called
//! PRINT, which uses 'print_stack', 'margin' and 'space' to figure out what to
//! do with each token/size pair it consumes as it goes. It's trying to consume
//! the entire buffered window, but can't output anything until the size is >=
//! 0 (sizes are set to negative while they're pending calculation).
//!
//! So SCAN takes input and buffers tokens and pending calculations, while
//! PRINT gobbles up completed calculations and tokens from the buffer. The
//! theory is that the two can never get more than 3N tokens apart, because
//! once there's "obviously" too much data to fit on a line, in a size
//! calculation, SCAN will write "infinity" to the size and let PRINT consume
//! it.
//!
//! In this implementation (following the paper, again) the SCAN process is
//! the method called `Printer::pretty_print`, and the 'PRINT' process is the method
//! called `Printer::print`.
use std::collections::VecDeque;
use std::fmt;
use std::io;
/// How to break. Described in more detail in the module docs.
#[derive(Clone, Copy, PartialEq)]
pub enum Breaks {
Consistent,
@ -177,81 +261,6 @@ pub fn mk_printer<'a>(out: Box<io::Write+'a>, linewidth: usize) -> Printer<'a> {
}
}
/// In case you do not have the paper, here is an explanation of what's going
/// on.
///
/// There is a stream of input tokens flowing through this printer.
///
/// The printer buffers up to 3N tokens inside itself, where N is linewidth.
/// Yes, linewidth is chars and tokens are multi-char, but in the worst
/// case every token worth buffering is 1 char long, so it's ok.
///
/// Tokens are String, Break, and Begin/End to delimit blocks.
///
/// Begin tokens can carry an offset, saying "how far to indent when you break
/// inside here", as well as a flag indicating "consistent" or "inconsistent"
/// breaking. Consistent breaking means that after the first break, no attempt
/// will be made to flow subsequent breaks together onto lines. Inconsistent
/// is the opposite. Inconsistent breaking example would be, say:
///
/// foo(hello, there, good, friends)
///
/// breaking inconsistently to become
///
/// foo(hello, there
/// good, friends);
///
/// whereas a consistent breaking would yield:
///
/// foo(hello,
/// there
/// good,
/// friends);
///
/// That is, in the consistent-break blocks we value vertical alignment
/// more than the ability to cram stuff onto a line. But in all cases if it
/// can make a block a one-liner, it'll do so.
///
/// Carrying on with high-level logic:
///
/// The buffered tokens go through a ring-buffer, 'tokens'. The 'left' and
/// 'right' indices denote the active portion of the ring buffer as well as
/// describing hypothetical points-in-the-infinite-stream at most 3N tokens
/// apart (i.e. "not wrapped to ring-buffer boundaries"). The paper will switch
/// between using 'left' and 'right' terms to denote the wrapped-to-ring-buffer
/// and point-in-infinite-stream senses freely.
///
/// There is a parallel ring buffer, 'size', that holds the calculated size of
/// each token. Why calculated? Because for Begin/End pairs, the "size"
/// includes everything between the pair. That is, the "size" of Begin is
/// actually the sum of the sizes of everything between Begin and the paired
/// End that follows. Since that is arbitrarily far in the future, 'size' is
/// being rewritten regularly while the printer runs; in fact most of the
/// machinery is here to work out 'size' entries on the fly (and give up when
/// they're so obviously over-long that "infinity" is a good enough
/// approximation for purposes of line breaking).
///
/// The "input side" of the printer is managed as an abstract process called
/// SCAN, which uses 'scan_stack', to manage calculating 'size'. SCAN is, in
/// other words, the process of calculating 'size' entries.
///
/// The "output side" of the printer is managed by an abstract process called
/// PRINT, which uses 'print_stack', 'margin' and 'space' to figure out what to
/// do with each token/size pair it consumes as it goes. It's trying to consume
/// the entire buffered window, but can't output anything until the size is >=
/// 0 (sizes are set to negative while they're pending calculation).
///
/// So SCAN takes input and buffers tokens and pending calculations, while
/// PRINT gobbles up completed calculations and tokens from the buffer. The
/// theory is that the two can never get more than 3N tokens apart, because
/// once there's "obviously" too much data to fit on a line, in a size
/// calculation, SCAN will write "infinity" to the size and let PRINT consume
/// it.
///
/// In this implementation (following the paper, again) the SCAN process is
/// the method called 'pretty_print', and the 'PRINT' process is the method
/// called 'print'.
pub struct Printer<'a> {
pub out: Box<io::Write+'a>,
buf_len: usize,
@ -292,7 +301,7 @@ impl<'a> Printer<'a> {
pub fn last_token(&mut self) -> Token {
self.buf[self.right].token.clone()
}
// be very careful with this!
/// be very careful with this!
pub fn replace_last_token(&mut self, t: Token) {
self.buf[self.right].token = t;
}
@ -571,8 +580,8 @@ impl<'a> Printer<'a> {
}
// Convenience functions to talk to the printer.
//
// "raw box"
/// "raw box"
pub fn rbox(p: &mut Printer, indent: usize, b: Breaks) -> io::Result<()> {
p.pretty_print(Token::Begin(BeginToken {
offset: indent as isize,
@ -580,10 +589,12 @@ pub fn rbox(p: &mut Printer, indent: usize, b: Breaks) -> io::Result<()> {
}))
}
/// Inconsistent breaking box
pub fn ibox(p: &mut Printer, indent: usize) -> io::Result<()> {
rbox(p, indent, Breaks::Inconsistent)
}
/// Consistent breaking box
pub fn cbox(p: &mut Printer, indent: usize) -> io::Result<()> {
rbox(p, indent, Breaks::Consistent)
}

View File

@ -513,7 +513,7 @@ extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateFunction(
extern "C" LLVMRustMetadataRef
LLVMRustDIBuilderCreateBasicType(LLVMRustDIBuilderRef Builder, const char *Name,
uint64_t SizeInBits, uint64_t AlignInBits,
uint64_t SizeInBits, uint32_t AlignInBits,
unsigned Encoding) {
return wrap(Builder->createBasicType(Name, SizeInBits,
#if LLVM_VERSION_LE(3, 9)
@ -524,7 +524,7 @@ LLVMRustDIBuilderCreateBasicType(LLVMRustDIBuilderRef Builder, const char *Name,
extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreatePointerType(
LLVMRustDIBuilderRef Builder, LLVMRustMetadataRef PointeeTy,
uint64_t SizeInBits, uint64_t AlignInBits, const char *Name) {
uint64_t SizeInBits, uint32_t AlignInBits, const char *Name) {
return wrap(Builder->createPointerType(unwrapDI<DIType>(PointeeTy),
SizeInBits, AlignInBits, Name));
}
@ -532,7 +532,7 @@ extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreatePointerType(
extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateStructType(
LLVMRustDIBuilderRef Builder, LLVMRustMetadataRef Scope, const char *Name,
LLVMRustMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
uint64_t AlignInBits, LLVMRustDIFlags Flags,
uint32_t AlignInBits, LLVMRustDIFlags Flags,
LLVMRustMetadataRef DerivedFrom, LLVMRustMetadataRef Elements,
unsigned RunTimeLang, LLVMRustMetadataRef VTableHolder,
const char *UniqueId) {
@ -546,7 +546,7 @@ extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateStructType(
extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateMemberType(
LLVMRustDIBuilderRef Builder, LLVMRustMetadataRef Scope, const char *Name,
LLVMRustMetadataRef File, unsigned LineNo, uint64_t SizeInBits,
uint64_t AlignInBits, uint64_t OffsetInBits, LLVMRustDIFlags Flags,
uint32_t AlignInBits, uint64_t OffsetInBits, LLVMRustDIFlags Flags,
LLVMRustMetadataRef Ty) {
return wrap(Builder->createMemberType(unwrapDI<DIDescriptor>(Scope), Name,
unwrapDI<DIFile>(File), LineNo,
@ -573,7 +573,7 @@ extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateStaticVariable(
LLVMRustDIBuilderRef Builder, LLVMRustMetadataRef Context, const char *Name,
const char *LinkageName, LLVMRustMetadataRef File, unsigned LineNo,
LLVMRustMetadataRef Ty, bool IsLocalToUnit, LLVMValueRef V,
LLVMRustMetadataRef Decl = nullptr, uint64_t AlignInBits = 0) {
LLVMRustMetadataRef Decl = nullptr, uint32_t AlignInBits = 0) {
Constant *InitVal = cast<Constant>(unwrap(V));
#if LLVM_VERSION_GE(4, 0)
@ -612,7 +612,7 @@ extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateVariable(
LLVMRustDIBuilderRef Builder, unsigned Tag, LLVMRustMetadataRef Scope,
const char *Name, LLVMRustMetadataRef File, unsigned LineNo,
LLVMRustMetadataRef Ty, bool AlwaysPreserve, LLVMRustDIFlags Flags,
unsigned ArgNo, uint64_t AlignInBits) {
unsigned ArgNo, uint32_t AlignInBits) {
#if LLVM_VERSION_GE(3, 8)
if (Tag == 0x100) { // DW_TAG_auto_variable
return wrap(Builder->createAutoVariable(
@ -637,7 +637,7 @@ extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateVariable(
extern "C" LLVMRustMetadataRef
LLVMRustDIBuilderCreateArrayType(LLVMRustDIBuilderRef Builder, uint64_t Size,
uint64_t AlignInBits, LLVMRustMetadataRef Ty,
uint32_t AlignInBits, LLVMRustMetadataRef Ty,
LLVMRustMetadataRef Subscripts) {
return wrap(
Builder->createArrayType(Size, AlignInBits, unwrapDI<DIType>(Ty),
@ -646,7 +646,7 @@ LLVMRustDIBuilderCreateArrayType(LLVMRustDIBuilderRef Builder, uint64_t Size,
extern "C" LLVMRustMetadataRef
LLVMRustDIBuilderCreateVectorType(LLVMRustDIBuilderRef Builder, uint64_t Size,
uint64_t AlignInBits, LLVMRustMetadataRef Ty,
uint32_t AlignInBits, LLVMRustMetadataRef Ty,
LLVMRustMetadataRef Subscripts) {
return wrap(
Builder->createVectorType(Size, AlignInBits, unwrapDI<DIType>(Ty),
@ -687,7 +687,7 @@ LLVMRustDIBuilderCreateEnumerator(LLVMRustDIBuilderRef Builder,
extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateEnumerationType(
LLVMRustDIBuilderRef Builder, LLVMRustMetadataRef Scope, const char *Name,
LLVMRustMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
uint64_t AlignInBits, LLVMRustMetadataRef Elements,
uint32_t AlignInBits, LLVMRustMetadataRef Elements,
LLVMRustMetadataRef ClassTy) {
return wrap(Builder->createEnumerationType(
unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), LineNumber,
@ -698,7 +698,7 @@ extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateEnumerationType(
extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateUnionType(
LLVMRustDIBuilderRef Builder, LLVMRustMetadataRef Scope, const char *Name,
LLVMRustMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
uint64_t AlignInBits, LLVMRustDIFlags Flags, LLVMRustMetadataRef Elements,
uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMRustMetadataRef Elements,
unsigned RunTimeLang, const char *UniqueId) {
return wrap(Builder->createUnionType(
unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), LineNumber,

View File

@ -29,6 +29,9 @@ pub type RustBadRet = extern fn() -> Box<u32>;
pub type CVoidRet = ();
pub struct Foo;
#[repr(C)]
pub struct ZeroSizeWithPhantomData(::std::marker::PhantomData<i32>);
extern {
pub fn ptr_type1(size: *const Foo); //~ ERROR: found struct without
pub fn ptr_type2(size: *const Foo); //~ ERROR: found struct without
@ -40,6 +43,9 @@ extern {
pub fn tuple_type(p: (i32, i32)); //~ ERROR found Rust tuple type
pub fn tuple_type2(p: I32Pair); //~ ERROR found Rust tuple type
pub fn zero_size(p: ZeroSize); //~ ERROR found zero-size struct
pub fn zero_size_phantom(p: ZeroSizeWithPhantomData); //~ ERROR found zero-sized type
pub fn zero_size_phantom_toplevel()
-> ::std::marker::PhantomData<bool>; //~ ERROR: found zero-sized type
pub fn fn_type(p: RustFn); //~ ERROR found function pointer with Rust
pub fn fn_type2(p: fn()); //~ ERROR found function pointer with Rust
pub fn fn_contained(p: RustBadRet); //~ ERROR: found struct without

View File

@ -0,0 +1,38 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Regression test for a weird corner case in our dep-graph reduction
// code. When we solve `CoerceUnsized<Foo>`, we find no impls, so we
// don't end up with an edge to any HIR nodes, but it still gets
// preserved in the dep graph.
// revisions:rpass1 rpass2
// compile-flags: -Z query-dep-graph
use std::sync::Arc;
#[cfg(rpass1)]
struct Foo { x: usize }
#[cfg(rpass1)]
fn main() {
let x: Arc<Foo> = Arc::new(Foo { x: 22 });
let y: Arc<Foo> = x;
}
#[cfg(rpass2)]
struct FooX { x: usize }
#[cfg(rpass2)]
fn main() {
let x: Arc<FooX> = Arc::new(FooX { x: 22 });
let y: Arc<FooX> = x;
}

View File

@ -0,0 +1,34 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![forbid(improper_ctypes)]
#![allow(dead_code)]
#[repr(C)]
pub struct Foo {
size: u8,
__value: ::std::marker::PhantomData<i32>,
}
#[repr(C)]
pub struct ZeroSizeWithPhantomData<T>(::std::marker::PhantomData<T>);
#[repr(C)]
pub struct Bar {
size: u8,
baz: ZeroSizeWithPhantomData<i32>,
}
extern "C" {
pub fn bar(_: *mut Foo, _: *mut Bar);
}
fn main() {
}

View File

@ -13,7 +13,6 @@
#![feature(process_try_wait)]
use std::env;
use std::io;
use std::process::Command;
use std::thread;
use std::time::Duration;
@ -32,17 +31,17 @@ fn main() {
.arg("sleep")
.spawn()
.unwrap();
let err = me.try_wait().unwrap_err();
assert_eq!(err.kind(), io::ErrorKind::WouldBlock);
let err = me.try_wait().unwrap_err();
assert_eq!(err.kind(), io::ErrorKind::WouldBlock);
let maybe_status = me.try_wait().unwrap();
assert!(maybe_status.is_none());
let maybe_status = me.try_wait().unwrap();
assert!(maybe_status.is_none());
me.kill().unwrap();
me.wait().unwrap();
let status = me.try_wait().unwrap();
let status = me.try_wait().unwrap().unwrap();
assert!(!status.success());
let status = me.try_wait().unwrap();
let status = me.try_wait().unwrap().unwrap();
assert!(!status.success());
let mut me = Command::new(env::current_exe().unwrap())
@ -51,17 +50,17 @@ fn main() {
.unwrap();
loop {
match me.try_wait() {
Ok(res) => {
Ok(Some(res)) => {
assert!(res.success());
break
}
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
Ok(None) => {
thread::sleep(Duration::from_millis(1));
}
Err(e) => panic!("error in try_wait: {}", e),
}
}
let status = me.try_wait().unwrap();
let status = me.try_wait().unwrap().unwrap();
assert!(status.success());
}

View File

@ -0,0 +1,19 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// compile-flags: --test
// check-test-line-numbers-match
/// This looks like another awesome test!
///
/// ```
/// println!("foo?");
/// ```
pub fn foooo() {}

View File

@ -11,6 +11,8 @@
// compile-flags: --test
// check-test-line-numbers-match
pub mod bar;
/// This is a Foo;
///
/// ```

View File

@ -11,7 +11,7 @@
extern crate toml;
extern crate rustc_serialize;
use std::collections::HashMap;
use std::collections::{BTreeMap, HashMap};
use std::env;
use std::fs::File;
use std::io::{self, Read, Write};
@ -95,7 +95,6 @@ static MINGW: &'static [&'static str] = &[
"x86_64-pc-windows-gnu",
];
#[derive(RustcEncodable)]
struct Manifest {
manifest_version: String,
date: String,
@ -171,8 +170,18 @@ impl Builder {
self.cargo_version = self.version("cargo", "x86_64-unknown-linux-gnu");
self.digest_and_sign();
let manifest = self.build_manifest();
let manifest = toml::encode(&manifest).to_string();
let Manifest { manifest_version, date, pkg } = self.build_manifest();
// Unfortunately we can't use derive(RustcEncodable) here because the
// version field is called `manifest-version`, not `manifest_version`.
// In lieu of that just create the table directly here with a `BTreeMap`
// and wrap it up in a `Value::Table`.
let mut manifest = BTreeMap::new();
manifest.insert("manifest-version".to_string(),
toml::encode(&manifest_version));
manifest.insert("date".to_string(), toml::encode(&date));
manifest.insert("pkg".to_string(), toml::encode(&pkg));
let manifest = toml::Value::Table(manifest).to_string();
let filename = format!("channel-rust-{}.toml", self.channel);
self.write_manifest(&manifest, &filename);

View File

@ -30,6 +30,7 @@ use std::io::{self, BufReader};
use std::path::{Path, PathBuf};
use std::process::{Command, Output, ExitStatus};
use std::str;
use std::collections::HashMap;
use extract_gdb_version;
@ -1942,17 +1943,28 @@ actual:\n\
}
}
fn check_rustdoc_test_option(&self, res: ProcRes) {
let mut file = fs::File::open(&self.testpaths.file)
fn get_lines<P: AsRef<Path>>(&self, path: &P,
mut other_files: Option<&mut Vec<String>>) -> Vec<usize> {
let mut file = fs::File::open(path)
.expect("markdown_test_output_check_entry File::open failed");
let mut content = String::new();
file.read_to_string(&mut content)
.expect("markdown_test_output_check_entry read_to_string failed");
let mut ignore = false;
let mut v: Vec<usize> =
content.lines()
.enumerate()
.filter_map(|(line_nb, line)| {
content.lines()
.enumerate()
.filter_map(|(line_nb, line)| {
if (line.trim_left().starts_with("pub mod ") ||
line.trim_left().starts_with("mod ")) &&
line.ends_with(";") {
if let Some(ref mut other_files) = other_files {
other_files.push(line.rsplit("mod ")
.next()
.unwrap()
.replace(";", ""));
}
None
} else {
let sline = line.split("///").last().unwrap_or("");
let line = sline.trim_left();
if line.starts_with("```") {
@ -1966,8 +1978,21 @@ actual:\n\
} else {
None
}
})
.collect();
}
})
.collect()
}
fn check_rustdoc_test_option(&self, res: ProcRes) {
let mut other_files = Vec::new();
let mut files: HashMap<String, Vec<usize>> = HashMap::new();
files.insert(self.testpaths.file.to_str().unwrap().to_owned(),
self.get_lines(&self.testpaths.file, Some(&mut other_files)));
for other_file in other_files {
let mut path = self.testpaths.file.clone();
path.set_file_name(&format!("{}.rs", other_file));
files.insert(path.to_str().unwrap().to_owned(), self.get_lines(&path, None));
}
let mut tested = 0;
for _ in res.stdout.split("\n")
@ -1975,27 +2000,35 @@ actual:\n\
.inspect(|s| {
let tmp: Vec<&str> = s.split(" - line ").collect();
if tmp.len() == 2 {
tested += 1;
let line = tmp[1].split(" ...")
.next()
.unwrap_or("0")
.parse()
.unwrap_or(0);
if let Ok(pos) = v.binary_search(&line) {
v.remove(pos);
} else {
self.fatal_proc_rec(
&format!("Not found doc test: \"{}\" in {:?}", s, v),
&res);
let path = tmp[0].rsplit("test ").next().unwrap();
if let Some(ref mut v) = files.get_mut(path) {
tested += 1;
let line = tmp[1].split(" ...")
.next()
.unwrap_or("0")
.parse()
.unwrap_or(0);
if let Ok(pos) = v.binary_search(&line) {
v.remove(pos);
} else {
self.fatal_proc_rec(
&format!("Not found doc test: \"{}\" in \"{}\":{:?}",
s, path, v),
&res);
}
}
}
}) {}
if tested == 0 {
self.fatal_proc_rec("No test has been found", &res);
} else if v.len() != 0 {
self.fatal_proc_rec(&format!("Not found test at line{} {:?}",
if v.len() > 1 { "s" } else { "" }, v),
&res);
self.fatal_proc_rec(&format!("No test has been found... {:?}", files), &res);
} else {
for (entry, v) in &files {
if v.len() != 0 {
self.fatal_proc_rec(&format!("Not found test at line{} \"{}\":{:?}",
if v.len() > 1 { "s" } else { "" }, entry, v),
&res);
}
}
}
}