Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rolling up PRs in the queue #23936

Merged
merged 56 commits into from
Apr 1, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
62645a1
Fix ICE when dividing integral SIMD types.
hirschenberger Mar 25, 2015
6370f29
std: Stabilize parts of std::os::platform::io
alexcrichton Mar 26, 2015
df65f59
replace deprecated as_slice()
demelev Mar 30, 2015
2a89d69
libcore: Ensure min and max functions are consistent for equal inputs
Ryman Mar 30, 2015
f19e763
std: Stabilize the rest of Any/BoxAny
alexcrichton Mar 30, 2015
e17f4fc
convert: remove FromError, use From<E> instead
seanmonstar Mar 31, 2015
606f50c
Lex binary and octal literals more eagerly.
huonw Mar 30, 2015
a78d383
Update lib.rs
wettowelreactor Mar 31, 2015
edc096d
Document std::borrow with examples
steveklabnik Mar 24, 2015
fe8a660
Last docs for std::env
steveklabnik Mar 31, 2015
5872ae4
Indicate select! is code-like
frewsxcv Mar 31, 2015
5d0beb7
rollup merge of #23549: aturon/stab-num
alexcrichton Mar 31, 2015
03c2f33
rollup merge of #23669: steveklabnik/doc_std_borrow
alexcrichton Mar 31, 2015
9fc51ef
Stabilize `std::convert` and related code
aturon Mar 30, 2015
cf56162
Fix up iterator documentation with regards to for loop sugar
steveklabnik Mar 31, 2015
9ba7974
book: reword timer bit
Mar 31, 2015
d9a6e86
Fixup primitive.str docs
steveklabnik Mar 31, 2015
5cf126a
std: Remove #[old_orphan_check] from PartialEq
alexcrichton Mar 11, 2015
608fff8
rustc: Remove old_orphan_check entirely
alexcrichton Mar 31, 2015
e48c7c6
Fix spelling
steveklabnik Mar 31, 2015
71982aa
std: Add a process::exit function
alexcrichton Mar 31, 2015
b9ab5fe
Stabilize a few remaining stragglers
aturon Mar 31, 2015
1829974
rollup merge of #23704: hirschenberger/simd-intdiv-ice
alexcrichton Mar 31, 2015
890f0ab
rollup merge of #23766: alexcrichton/stabilize-raw-fd
alexcrichton Mar 31, 2015
d03120a
rollup merge of #23876: alexcrichton/stabilize-any
alexcrichton Mar 31, 2015
f6bd6b4
rollup merge of #23878: Ryman/stable_extremes
alexcrichton Mar 31, 2015
095f1fb
rollup merge of #23882: wettowelreactor/patch-2
alexcrichton Mar 31, 2015
5e0bda0
rollup merge of #23885: steveklabnik/doc_std_env
alexcrichton Mar 31, 2015
6d2c640
rollup merge of #23886: demelev/remove_as_slice_usage
alexcrichton Mar 31, 2015
acdb0f9
rollup merge of #23893: frewsxcv/patch-6
alexcrichton Mar 31, 2015
d4a2c94
std: Clean out #[deprecated] APIs
alexcrichton Mar 30, 2015
e3f2d45
rollup merge of #23872: huonw/eager-lexing
alexcrichton Mar 31, 2015
94137a3
Test fixes and rebase conflicts, round 1
alexcrichton Mar 31, 2015
da04788
rollup merge of #23875: aturon/revise-convert-2
alexcrichton Mar 31, 2015
e10ee2c
rollup merge of #23879: seanmonstar/del-from-error
alexcrichton Mar 31, 2015
554946c
rollup merge of #23873: alexcrichton/remove-deprecated
alexcrichton Mar 31, 2015
3053288
Test fixes and rebase conflicts, round 2
alexcrichton Mar 31, 2015
82889f7
rollup merge of #23902: freebroccolo/master
alexcrichton Mar 31, 2015
0cac5b6
rollup merge of #23906: steveklabnik/spellin
alexcrichton Mar 31, 2015
a37311d
rollup merge of #23907: alexcrichton/impl-exit
alexcrichton Mar 31, 2015
30283d4
rollup merge of #23908: aturon/stab-more-stragglers
alexcrichton Mar 31, 2015
3422be3
rollup merge of #23288: alexcrichton/issue-19470
alexcrichton Mar 31, 2015
8da0831
Move benchmark tests to unstable section
steveklabnik Mar 31, 2015
9ab6cc9
rollup merge of #23901: steveklabnik/fix_links_str
alexcrichton Mar 31, 2015
6659865
rollup merge of #23920: steveklabnik/gh23881
alexcrichton Mar 31, 2015
ac77392
std: Stabilize last bits of io::Error
alexcrichton Mar 31, 2015
85e997a
rollup merge of #23899: steveklabnik/gh23851
alexcrichton Mar 31, 2015
50b3ecf
rollup merge of #23919: alexcrichton/stabilize-io-error
alexcrichton Mar 31, 2015
55e531d
Add test for #17746
aturon Mar 31, 2015
371ba00
Add description of + for multiple trait bounds
steveklabnik Mar 31, 2015
72f5973
Test fixes and rebase conflicts, round 3
alexcrichton Mar 31, 2015
4f643d7
rollup merge of #23863: pnkfelix/arith-oflo-const-eval
alexcrichton Apr 1, 2015
1d5ef75
rollup merge of #23921: aturon/issue-17746
alexcrichton Apr 1, 2015
6ebb6e6
rollup merge of #23923: steveklabnik/gh23688
alexcrichton Apr 1, 2015
8dff0ac
Test fixes and rebase conflicts
alexcrichton Apr 1, 2015
2b71aed
Update android tests to reflect API switch from `os::env` to `env::va…
pnkfelix Apr 1, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/compiletest/compiletest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
#![feature(std_misc)]
#![feature(test)]
#![feature(path_ext)]
#![feature(convert)]
#![feature(str_char)]

#![deny(warnings)]
Expand Down
4 changes: 0 additions & 4 deletions src/doc/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -977,17 +977,13 @@ An example of `use` declarations:

```
# #![feature(core)]
use std::iter::range_step;
use std::option::Option::{Some, None};
use std::collections::hash_map::{self, HashMap};

fn foo<T>(_: T){}
fn bar(map1: HashMap<String, usize>, map2: hash_map::HashMap<String, usize>){}

fn main() {
// Equivalent to 'std::iter::range_step(0, 10, 2);'
range_step(0, 10, 2);

// Equivalent to 'foo(vec![std::option::Option::Some(1.0f64),
// std::option::Option::None]);'
foo(vec![Some(1.0f64), None]);
Expand Down
1 change: 1 addition & 0 deletions src/doc/trpl/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,6 @@
* [Intrinsics](intrinsics.md)
* [Lang items](lang-items.md)
* [Link args](link-args.md)
* [Benchmark Tests](benchmark-tests.md)
* [Conclusion](conclusion.md)
* [Glossary](glossary.md)
152 changes: 152 additions & 0 deletions src/doc/trpl/benchmark-tests.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
% Benchmark tests

Rust supports benchmark tests, which can test the performance of your
code. Let's make our `src/lib.rs` look like this (comments elided):

```{rust,ignore}
#![feature(test)]

extern crate test;

pub fn add_two(a: i32) -> i32 {
a + 2
}

#[cfg(test)]
mod tests {
use super::*;
use test::Bencher;

#[test]
fn it_works() {
assert_eq!(4, add_two(2));
}

#[bench]
fn bench_add_two(b: &mut Bencher) {
b.iter(|| add_two(2));
}
}
```

Note the `test` feature gate, which enables this unstable feature.

We've imported the `test` crate, which contains our benchmarking support.
We have a new function as well, with the `bench` attribute. Unlike regular
tests, which take no arguments, benchmark tests take a `&mut Bencher`. This
`Bencher` provides an `iter` method, which takes a closure. This closure
contains the code we'd like to benchmark.

We can run benchmark tests with `cargo bench`:

```bash
$ cargo bench
Compiling adder v0.0.1 (file:///home/steve/tmp/adder)
Running target/release/adder-91b3e234d4ed382a

running 2 tests
test tests::it_works ... ignored
test tests::bench_add_two ... bench: 1 ns/iter (+/- 0)

test result: ok. 0 passed; 0 failed; 1 ignored; 1 measured
```

Our non-benchmark test was ignored. You may have noticed that `cargo bench`
takes a bit longer than `cargo test`. This is because Rust runs our benchmark
a number of times, and then takes the average. Because we're doing so little
work in this example, we have a `1 ns/iter (+/- 0)`, but this would show
the variance if there was one.

Advice on writing benchmarks:


* Move setup code outside the `iter` loop; only put the part you want to measure inside
* Make the code do "the same thing" on each iteration; do not accumulate or change state
* Make the outer function idempotent too; the benchmark runner is likely to run
it many times
* Make the inner `iter` loop short and fast so benchmark runs are fast and the
calibrator can adjust the run-length at fine resolution
* Make the code in the `iter` loop do something simple, to assist in pinpointing
performance improvements (or regressions)

## Gotcha: optimizations

There's another tricky part to writing benchmarks: benchmarks compiled with
optimizations activated can be dramatically changed by the optimizer so that
the benchmark is no longer benchmarking what one expects. For example, the
compiler might recognize that some calculation has no external effects and
remove it entirely.

```{rust,ignore}
#![feature(test)]

extern crate test;
use test::Bencher;

#[bench]
fn bench_xor_1000_ints(b: &mut Bencher) {
b.iter(|| {
(0..1000).fold(0, |old, new| old ^ new);
});
}
```

gives the following results

```text
running 1 test
test bench_xor_1000_ints ... bench: 0 ns/iter (+/- 0)

test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured
```

The benchmarking runner offers two ways to avoid this. Either, the closure that
the `iter` method receives can return an arbitrary value which forces the
optimizer to consider the result used and ensures it cannot remove the
computation entirely. This could be done for the example above by adjusting the
`b.iter` call to

```rust
# struct X;
# impl X { fn iter<T, F>(&self, _: F) where F: FnMut() -> T {} } let b = X;
b.iter(|| {
// note lack of `;` (could also use an explicit `return`).
(0..1000).fold(0, |old, new| old ^ new)
});
```

Or, the other option is to call the generic `test::black_box` function, which
is an opaque "black box" to the optimizer and so forces it to consider any
argument as used.

```rust
#![feature(test)]

extern crate test;

# fn main() {
# struct X;
# impl X { fn iter<T, F>(&self, _: F) where F: FnMut() -> T {} } let b = X;
b.iter(|| {
let n = test::black_box(1000);

(0..n).fold(0, |a, b| a ^ b)
})
# }
```

Neither of these read or modify the value, and are very cheap for small values.
Larger values can be passed indirectly to reduce overhead (e.g.
`black_box(&huge_struct)`).

Performing either of the above changes gives the following benchmarking results

```text
running 1 test
test bench_xor_1000_ints ... bench: 131 ns/iter (+/- 3)

test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured
```

However, the optimizer can still modify a testcase in an undesirable manner
even when using either of the above.
16 changes: 9 additions & 7 deletions src/doc/trpl/concurrency.md
Original file line number Diff line number Diff line change
Expand Up @@ -280,13 +280,15 @@ it returns an `Result<T, E>`, and because this is just an example, we `unwrap()`
it to get a reference to the data. Real code would have more robust error handling
here. We're then free to mutate it, since we have the lock.

This timer bit is a bit awkward, however. We have picked a reasonable amount of
time to wait, but it's entirely possible that we've picked too high, and that
we could be taking less time. It's also possible that we've picked too low,
and that we aren't actually finishing this computation.

Rust's standard library provides a few more mechanisms for two threads to
synchronize with each other. Let's talk about one: channels.
Lastly, while the threads are running, we wait on a short timer. But
this is not ideal: we may have picked a reasonable amount of time to
wait but it's more likely we'll either be waiting longer than
necessary or not long enough, depending on just how much time the
threads actually take to finish computing when the program runs.

A more precise alternative to the timer would be to use one of the
mechanisms provided by the Rust standard library for synchronizing
threads with each other. Let's talk about one of them: channels.

## Channels

Expand Down
13 changes: 7 additions & 6 deletions src/doc/trpl/iterators.md
Original file line number Diff line number Diff line change
Expand Up @@ -243,11 +243,12 @@ for num in nums.iter() {
```

These two basic iterators should serve you well. There are some more
advanced iterators, including ones that are infinite. Like `count`:
advanced iterators, including ones that are infinite. Like using range syntax
and `step_by`:

```rust
# #![feature(core)]
std::iter::count(1, 5);
# #![feature(step_by)]
(1..).step_by(5);
```

This iterator counts up from one, adding five each time. It will give
Expand Down Expand Up @@ -292,11 +293,11 @@ just use `for` instead.
There are tons of interesting iterator adapters. `take(n)` will return an
iterator over the next `n` elements of the original iterator, note that this
has no side effect on the original iterator. Let's try it out with our infinite
iterator from before, `count()`:
iterator from before:

```rust
# #![feature(core)]
for i in std::iter::count(1, 5).take(5) {
# #![feature(step_by)]
for i in (1..).step_by(5).take(5) {
println!("{}", i);
}
```
Expand Down
6 changes: 3 additions & 3 deletions src/doc/trpl/macros.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ number of elements.

```rust
let x: Vec<u32> = vec![1, 2, 3];
# assert_eq!(&[1,2,3], &x);
# assert_eq!(x, [1, 2, 3]);
```

This can't be an ordinary function, because it takes any number of arguments.
Expand All @@ -51,7 +51,7 @@ let x: Vec<u32> = {
temp_vec.push(3);
temp_vec
};
# assert_eq!(&[1,2,3], &x);
# assert_eq!(x, [1, 2, 3]);
```

We can implement this shorthand, using a macro: [^actual]
Expand All @@ -73,7 +73,7 @@ macro_rules! vec {
};
}
# fn main() {
# assert_eq!([1,2,3], vec![1,2,3]);
# assert_eq!(vec![1,2,3], [1, 2, 3]);
# }
```

Expand Down
2 changes: 1 addition & 1 deletion src/doc/trpl/ownership.md
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@ forbidden in item signatures to allow reasoning about the types just based in
the item signature alone. However, for ergonomic reasons a very restricted
secondary inference algorithm called “lifetime elision” applies in function
signatures. It infers only based on the signature components themselves and not
based on the body of the function, only infers lifetime paramters, and does
based on the body of the function, only infers lifetime parameters, and does
this with only three easily memorizable and unambiguous rules. This makes
lifetime elision a shorthand for writing an item signature, while not hiding
away the actual types involved as full local inference would if applied to it.
Expand Down
Loading