Skip to content

Commit 256aeb7

Browse files
committed
---
yaml --- r: 156250 b: refs/heads/snap-stage3 c: 38517d0 h: refs/heads/master v: v3
1 parent adaeb41 commit 256aeb7

File tree

14 files changed

+187
-53
lines changed

14 files changed

+187
-53
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
refs/heads/master: c29a7520e7fb4a5b4d4eccfc594e05793ef6688d
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
4-
refs/heads/snap-stage3: 4442e6d890136dd20b807140f60718d62f023392
4+
refs/heads/snap-stage3: 38517d0eba2ee69443449fbe6b1ce7dea7deca7b
55
refs/heads/try: 6601b0501e31d08d3892a2d5a7d8a57ab120bf75
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b

branches/snap-stage3/mk/crates.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ DEPS_regex := std
101101
DEPS_regex_macros = rustc syntax std regex
102102
DEPS_fmt_macros = std
103103

104-
TOOL_DEPS_compiletest := test getopts
104+
TOOL_DEPS_compiletest := test getopts native
105105
TOOL_DEPS_rustdoc := rustdoc native
106106
TOOL_DEPS_rustc := rustc native
107107
TOOL_SOURCE_compiletest := $(S)src/compiletest/compiletest.rs

branches/snap-stage3/src/compiletest/runtest.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -952,10 +952,10 @@ fn check_expected_errors(expected_errors: Vec<errors::ExpectedError> ,
952952
to_lower(line).as_slice().starts_with(to_lower(prefix).as_slice())
953953
}
954954

955-
#[cfg(target_os = "linux")]
956-
#[cfg(target_os = "macos")]
957-
#[cfg(target_os = "freebsd")]
958-
#[cfg(target_os = "dragonfly")]
955+
#[cfg(any(target_os = "linux",
956+
target_os = "macos",
957+
target_os = "freebsd",
958+
target_os = "dragonfly"))]
959959
fn prefix_matches( line : &str, prefix : &str ) -> bool {
960960
line.starts_with( prefix )
961961
}
@@ -1356,10 +1356,10 @@ fn program_output(config: &Config, testfile: &Path, lib_path: &str, prog: String
13561356
}
13571357

13581358
// Linux and mac don't require adjusting the library search path
1359-
#[cfg(target_os = "linux")]
1360-
#[cfg(target_os = "macos")]
1361-
#[cfg(target_os = "freebsd")]
1362-
#[cfg(target_os = "dragonfly")]
1359+
#[cfg(any(target_os = "linux",
1360+
target_os = "macos",
1361+
target_os = "freebsd",
1362+
target_os = "dragonfly"))]
13631363
fn make_cmdline(_libpath: &str, prog: &str, args: &[String]) -> String {
13641364
format!("{} {}", prog, args.connect(" "))
13651365
}

branches/snap-stage3/src/libcollections/btree/map.rs

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,47 @@ use ringbuf::RingBuf;
2929

3030

3131
/// A map based on a B-Tree.
32+
///
33+
/// B-Trees represent a fundamental compromise between cache-efficiency and actually minimizing
34+
/// the amount of work performed in a search. In theory, a binary search tree (BST) is the optimal
35+
/// choice for a sorted map, as a perfectly balanced BST performs the theoretical minimum amount of
36+
/// comparisons necessary to find an element (log<sub>2</sub>n). However, in practice the way this
37+
/// is done is *very* inefficient for modern computer architectures. In particular, every element
38+
/// is stored in its own individually heap-allocated node. This means that every single insertion
39+
/// triggers a heap-allocation, and every single comparison should be a cache-miss. Since these
40+
/// are both notably expensive things to do in practice, we are forced to at very least reconsider
41+
/// the BST strategy.
42+
///
43+
/// A B-Tree instead makes each node contain B-1 to 2B-1 elements in a contiguous array. By doing
44+
/// this, we reduce the number of allocations by a factor of B, and improve cache effeciency in
45+
/// searches. However, this does mean that searches will have to do *more* comparisons on average.
46+
/// The precise number of comparisons depends on the node search strategy used. For optimal cache
47+
/// effeciency, one could search the nodes linearly. For optimal comparisons, one could search
48+
/// the node using binary search. As a compromise, one could also perform a linear search
49+
/// that initially only checks every i<sup>th</sup> element for some choice of i.
50+
///
51+
/// Currently, our implementation simply performs naive linear search. This provides excellent
52+
/// performance on *small* nodes of elements which are cheap to compare. However in the future we
53+
/// would like to further explore choosing the optimal search strategy based on the choice of B,
54+
/// and possibly other factors. Using linear search, searching for a random element is expected
55+
/// to take O(B log<sub>B</sub>n) comparisons, which is generally worse than a BST. In practice,
56+
/// however, performance is excellent. `BTreeMap` is able to readily outperform `TreeMap` under
57+
/// many workloads, and is competetive where it doesn't. BTreeMap also generally *scales* better
58+
/// than TreeMap, making it more appropriate for large datasets.
59+
///
60+
/// However, `TreeMap` may still be more appropriate to use in many contexts. If elements are very
61+
/// large or expensive to compare, `TreeMap` may be more appropriate. It won't allocate any
62+
/// more space than is needed, and will perform the minimal number of comparisons necessary.
63+
/// `TreeMap` also provides much better performance stability guarantees. Generally, very few
64+
/// changes need to be made to update a BST, and two updates are expected to take about the same
65+
/// amount of time on roughly equal sized BSTs. However a B-Tree's performance is much more
66+
/// amortized. If a node is overfull, it must be split into two nodes. If a node is underfull, it
67+
/// may be merged with another. Both of these operations are relatively expensive to perform, and
68+
/// it's possible to force one to occur at every single level of the tree in a single insertion or
69+
/// deletion. In fact, a malicious or otherwise unlucky sequence of insertions and deletions can
70+
/// force this degenerate behaviour to occur on every operation. While the total amount of work
71+
/// done on each operation isn't *catastrophic*, and *is* still bounded by O(B log<sub>B</sub>n),
72+
/// it is certainly much slower when it does.
3273
#[deriving(Clone)]
3374
pub struct BTreeMap<K, V> {
3475
root: Node<K, V>,
@@ -93,6 +134,8 @@ impl<K: Ord, V> BTreeMap<K, V> {
93134
}
94135

95136
/// Makes a new empty BTreeMap with the given B.
137+
///
138+
/// B cannot be less than 2.
96139
pub fn with_b(b: uint) -> BTreeMap<K, V> {
97140
assert!(b > 1, "B must be greater than 1");
98141
BTreeMap {
@@ -1145,9 +1188,12 @@ mod test {
11451188

11461189
#[cfg(test)]
11471190
mod bench {
1148-
use test::Bencher;
1191+
use std::prelude::*;
1192+
use std::rand::{weak_rng, Rng};
1193+
use test::{Bencher, black_box};
11491194

11501195
use super::BTreeMap;
1196+
use MutableMap;
11511197
use deque::bench::{insert_rand_n, insert_seq_n, find_rand_n, find_seq_n};
11521198

11531199
#[bench]
@@ -1200,4 +1246,34 @@ mod bench {
12001246
let mut m : BTreeMap<uint,uint> = BTreeMap::new();
12011247
find_seq_n(10_000, &mut m, b);
12021248
}
1249+
1250+
fn bench_iter(b: &mut Bencher, size: uint) {
1251+
let mut map = BTreeMap::<uint, uint>::new();
1252+
let mut rng = weak_rng();
1253+
1254+
for _ in range(0, size) {
1255+
map.swap(rng.gen(), rng.gen());
1256+
}
1257+
1258+
b.iter(|| {
1259+
for entry in map.iter() {
1260+
black_box(entry);
1261+
}
1262+
});
1263+
}
1264+
1265+
#[bench]
1266+
pub fn iter_20(b: &mut Bencher) {
1267+
bench_iter(b, 20);
1268+
}
1269+
1270+
#[bench]
1271+
pub fn iter_1000(b: &mut Bencher) {
1272+
bench_iter(b, 1000);
1273+
}
1274+
1275+
#[bench]
1276+
pub fn iter_100000(b: &mut Bencher) {
1277+
bench_iter(b, 100000);
1278+
}
12031279
}

branches/snap-stage3/src/libcollections/btree/set.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ use core::fmt::Show;
2323
use {Mutable, Set, MutableSet, MutableMap, Map};
2424

2525
/// A set based on a B-Tree.
26+
///
27+
/// See BTreeMap's documentation for a detailed discussion of this collection's performance
28+
/// benefits and drawbacks.
2629
#[deriving(Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]
2730
pub struct BTreeSet<T>{
2831
map: BTreeMap<T, ()>,
@@ -65,6 +68,8 @@ impl<T: Ord> BTreeSet<T> {
6568
}
6669

6770
/// Makes a new BTreeSet with the given B.
71+
///
72+
/// B cannot be less than 2.
6873
pub fn with_b(b: uint) -> BTreeSet<T> {
6974
BTreeSet { map: BTreeMap::with_b(b) }
7075
}

branches/snap-stage3/src/libcollections/slice.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -277,12 +277,14 @@ pub trait CloneableVector<T> {
277277
}
278278

279279
/// Converts `self` into an owned vector, not making a copy if possible.
280+
/// Deprecated. Use 'to_vec'
281+
#[deprecated = "Replaced by `to_vec`"]
280282
fn into_vec(self) -> Vec<T>;
281283

282-
/// Deprecated. Use `into_vec`
283-
#[deprecated = "Replaced by `into_vec`"]
284+
/// Deprecated. Use `to_vec`
285+
#[deprecated = "Replaced by `to_vec`"]
284286
fn into_owned(self) -> Vec<T> {
285-
self.into_vec()
287+
self.to_vec()
286288
}
287289
}
288290

@@ -2328,9 +2330,9 @@ mod tests {
23282330
}
23292331

23302332
#[test]
2331-
fn test_into_vec() {
2333+
fn test_to_vec() {
23322334
let xs = box [1u, 2, 3];
2333-
let ys = xs.into_vec();
2335+
let ys = xs.to_vec();
23342336
assert_eq!(ys.as_slice(), [1u, 2, 3].as_slice());
23352337
}
23362338
}

branches/snap-stage3/src/libcollections/treemap.rs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2232,9 +2232,12 @@ mod test_treemap {
22322232

22332233
#[cfg(test)]
22342234
mod bench {
2235-
use test::Bencher;
2235+
use std::prelude::*;
2236+
use std::rand::{weak_rng, Rng};
2237+
use test::{Bencher, black_box};
22362238

22372239
use super::TreeMap;
2240+
use MutableMap;
22382241
use deque::bench::{insert_rand_n, insert_seq_n, find_rand_n, find_seq_n};
22392242

22402243
// Find seq
@@ -2288,6 +2291,36 @@ mod bench {
22882291
let mut m : TreeMap<uint,uint> = TreeMap::new();
22892292
find_seq_n(10_000, &mut m, b);
22902293
}
2294+
2295+
fn bench_iter(b: &mut Bencher, size: uint) {
2296+
let mut map = TreeMap::<uint, uint>::new();
2297+
let mut rng = weak_rng();
2298+
2299+
for _ in range(0, size) {
2300+
map.swap(rng.gen(), rng.gen());
2301+
}
2302+
2303+
b.iter(|| {
2304+
for entry in map.iter() {
2305+
black_box(entry);
2306+
}
2307+
});
2308+
}
2309+
2310+
#[bench]
2311+
pub fn iter_20(b: &mut Bencher) {
2312+
bench_iter(b, 20);
2313+
}
2314+
2315+
#[bench]
2316+
pub fn iter_1000(b: &mut Bencher) {
2317+
bench_iter(b, 1000);
2318+
}
2319+
2320+
#[bench]
2321+
pub fn iter_100000(b: &mut Bencher) {
2322+
bench_iter(b, 100000);
2323+
}
22912324
}
22922325

22932326
#[cfg(test)]

branches/snap-stage3/src/libcollections/trie.rs

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -949,8 +949,8 @@ macro_rules! iterator_impl {
949949
// rules, and are just manipulating raw pointers like there's no
950950
// such thing as invalid pointers and memory unsafety. The
951951
// reason is performance, without doing this we can get the
952-
// bench_iter_large microbenchmark down to about 30000 ns/iter
953-
// (using .unsafe_get to index self.stack directly, 38000
952+
// (now replaced) bench_iter_large microbenchmark down to about
953+
// 30000 ns/iter (using .unsafe_get to index self.stack directly, 38000
954954
// ns/iter with [] checked indexing), but this smashes that down
955955
// to 13500 ns/iter.
956956
//
@@ -1459,31 +1459,39 @@ mod test_map {
14591459
mod bench_map {
14601460
use std::prelude::*;
14611461
use std::rand::{weak_rng, Rng};
1462-
use test::Bencher;
1462+
use test::{Bencher, black_box};
14631463

14641464
use MutableMap;
14651465
use super::TrieMap;
14661466

1467-
#[bench]
1468-
fn bench_iter_small(b: &mut Bencher) {
1469-
let mut m = TrieMap::<uint>::new();
1467+
fn bench_iter(b: &mut Bencher, size: uint) {
1468+
let mut map = TrieMap::<uint>::new();
14701469
let mut rng = weak_rng();
1471-
for _ in range(0u, 20) {
1472-
m.insert(rng.gen(), rng.gen());
1470+
1471+
for _ in range(0, size) {
1472+
map.swap(rng.gen(), rng.gen());
14731473
}
14741474

1475-
b.iter(|| for _ in m.iter() {})
1475+
b.iter(|| {
1476+
for entry in map.iter() {
1477+
black_box(entry);
1478+
}
1479+
});
14761480
}
14771481

14781482
#[bench]
1479-
fn bench_iter_large(b: &mut Bencher) {
1480-
let mut m = TrieMap::<uint>::new();
1481-
let mut rng = weak_rng();
1482-
for _ in range(0u, 1000) {
1483-
m.insert(rng.gen(), rng.gen());
1484-
}
1483+
pub fn iter_20(b: &mut Bencher) {
1484+
bench_iter(b, 20);
1485+
}
14851486

1486-
b.iter(|| for _ in m.iter() {})
1487+
#[bench]
1488+
pub fn iter_1000(b: &mut Bencher) {
1489+
bench_iter(b, 1000);
1490+
}
1491+
1492+
#[bench]
1493+
pub fn iter_100000(b: &mut Bencher) {
1494+
bench_iter(b, 100000);
14871495
}
14881496

14891497
#[bench]

branches/snap-stage3/src/libcollections/vec.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -570,13 +570,6 @@ impl<T> Collection for Vec<T> {
570570
}
571571
}
572572

573-
impl<T: Clone> CloneableVector<T> for Vec<T> {
574-
#[deprecated = "call .clone() instead"]
575-
fn to_vec(&self) -> Vec<T> { self.clone() }
576-
#[deprecated = "move the vector instead"]
577-
fn into_vec(self) -> Vec<T> { self }
578-
}
579-
580573
// FIXME: #13996: need a way to mark the return value as `noalias`
581574
#[inline(never)]
582575
unsafe fn alloc_or_realloc<T>(ptr: *mut T, old_size: uint, size: uint) -> *mut T {

branches/snap-stage3/src/libcoretest/mem.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ fn size_of_basic() {
1919
}
2020

2121
#[test]
22-
#[cfg(target_arch = "x86")]
23-
#[cfg(target_arch = "arm")]
24-
#[cfg(target_arch = "mips")]
25-
#[cfg(target_arch = "mipsel")]
22+
#[cfg(any(target_arch = "x86",
23+
target_arch = "arm",
24+
target_arch = "mips",
25+
target_arch = "mipsel"))]
2626
fn size_of_32() {
2727
assert_eq!(size_of::<uint>(), 4u);
2828
assert_eq!(size_of::<*const uint>(), 4u);
@@ -51,10 +51,10 @@ fn align_of_basic() {
5151
}
5252

5353
#[test]
54-
#[cfg(target_arch = "x86")]
55-
#[cfg(target_arch = "arm")]
56-
#[cfg(target_arch = "mips")]
57-
#[cfg(target_arch = "mipsel")]
54+
#[cfg(any(target_arch = "x86",
55+
target_arch = "arm",
56+
target_arch = "mips",
57+
target_arch = "mipsel"))]
5858
fn align_of_32() {
5959
assert_eq!(align_of::<uint>(), 4u);
6060
assert_eq!(align_of::<*const uint>(), 4u);

branches/snap-stage3/src/libgraphviz/maybe_owned_vec.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ impl<'a,T:Clone> CloneableVector<T> for MaybeOwnedVector<'a,T> {
140140
impl<'a, T: Clone> Clone for MaybeOwnedVector<'a, T> {
141141
fn clone(&self) -> MaybeOwnedVector<'a, T> {
142142
match *self {
143-
Growable(ref v) => Growable(v.to_vec()),
143+
Growable(ref v) => Growable(v.clone()),
144144
Borrowed(v) => Borrowed(v)
145145
}
146146
}

branches/snap-stage3/src/librustc/middle/traits/select.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1014,7 +1014,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
10141014

10151015
ty::ty_tup(ref tys) => {
10161016
// (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
1017-
Ok(If(tys.to_owned()))
1017+
Ok(If(tys.clone()))
10181018
}
10191019

10201020
ty::ty_unboxed_closure(def_id, _) => {

branches/snap-stage3/src/librustc_back/rpath.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,7 @@ mod test {
200200
}
201201

202202
#[test]
203-
#[cfg(target_os = "linux")]
204-
#[cfg(target_os = "android")]
203+
#[cfg(any(target_os = "linux", target_os = "android"))]
205204
fn test_rpath_relative() {
206205
let config = &mut RPathConfig {
207206
os: abi::OsLinux,

0 commit comments

Comments
 (0)