Skip to content

Commit

Permalink
Auto merge of #61758 - Centril:rollup-ew2uxng, r=Centril
Browse files Browse the repository at this point in the history
Rollup of 9 pull requests

Successful merges:

 - #60187 (Generator optimization: Overlap locals that never have storage live at the same time)
 - #61348 (Implement Clone::clone_from for Option and Result)
 - #61568 (Use Symbol, Span in libfmt_macros)
 - #61632 (ci: Collect CPU usage statistics on Azure)
 - #61654 (use pattern matching for slices destructuring)
 - #61671 (implement nth_back for Range(Inclusive))
 - #61688 (is_fp and is_floating_point do the same thing, remove the former)
 - #61705 (Pass cflags rather than cxxflags to LLVM as CMAKE_C_FLAGS)
 - #61734 (Migrate rust-by-example to MdBook2)

Failed merges:

r? @ghost
  • Loading branch information
bors committed Jun 12, 2019
2 parents 05083c2 + 4748b5b commit c4797fa
Show file tree
Hide file tree
Showing 30 changed files with 579 additions and 234 deletions.
16 changes: 16 additions & 0 deletions .azure-pipelines/steps/run.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ steps:
- checkout: self
fetchDepth: 2

# Spawn a background process to collect CPU usage statistics which we'll upload
# at the end of the build. See the comments in the script here for more
# information.
- bash: python src/ci/cpu-usage-over-time.py &> cpu-usage.csv &
displayName: "Collect CPU-usage statistics in the background"

- bash: printenv | sort
displayName: Show environment variables

Expand Down Expand Up @@ -142,3 +148,13 @@ steps:
AWS_SECRET_ACCESS_KEY: $(AWS_SECRET_ACCESS_KEY)
condition: and(succeeded(), or(eq(variables.DEPLOY, '1'), eq(variables.DEPLOY_ALT, '1')))
displayName: Upload artifacts

# Upload CPU usage statistics that we've been gathering this whole time. Always
# execute this step in case we want to inspect failed builds, but don't let
# errors here ever fail the build since this is just informational.
- bash: aws s3 cp --acl public-read cpu-usage.csv s3://$DEPLOY_BUCKET/rustc-builds/$BUILD_SOURCEVERSION/cpu-$SYSTEM_JOBNAME.csv
env:
AWS_SECRET_ACCESS_KEY: $(AWS_SECRET_ACCESS_KEY)
condition: contains(variables, 'AWS_SECRET_ACCESS_KEY')
continueOnError: true
displayName: Upload CPU usage statistics
3 changes: 3 additions & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -910,6 +910,9 @@ dependencies = [
[[package]]
name = "fmt_macros"
version = "0.0.0"
dependencies = [
"syntax_pos 0.0.0",
]

[[package]]
name = "fnv"
Expand Down
2 changes: 1 addition & 1 deletion src/bootstrap/doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ book!(
EmbeddedBook, "src/doc/embedded-book", "embedded-book", RustbookVersion::MdBook2;
Nomicon, "src/doc/nomicon", "nomicon", RustbookVersion::MdBook2;
Reference, "src/doc/reference", "reference", RustbookVersion::MdBook1;
RustByExample, "src/doc/rust-by-example", "rust-by-example", RustbookVersion::MdBook1;
RustByExample, "src/doc/rust-by-example", "rust-by-example", RustbookVersion::MdBook2;
RustcBook, "src/doc/rustc", "rustc", RustbookVersion::MdBook1;
RustdocBook, "src/doc/rustdoc", "rustdoc", RustbookVersion::MdBook2;
);
Expand Down
2 changes: 1 addition & 1 deletion src/bootstrap/native.rs
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,7 @@ fn configure_cmake(builder: &Builder<'_>,

cfg.build_arg("-j").build_arg(builder.jobs().to_string());
let mut cflags = builder.cflags(target, GitRepo::Llvm).join(" ");
if let Some(ref s) = builder.config.llvm_cxxflags {
if let Some(ref s) = builder.config.llvm_cflags {
cflags.push_str(&format!(" {}", s));
}
cfg.define("CMAKE_C_FLAGS", cflags);
Expand Down
175 changes: 175 additions & 0 deletions src/ci/cpu-usage-over-time.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
#!/usr/bin/env python
# ignore-tidy-linelength

# This is a small script that we use on CI to collect CPU usage statistics of
# our builders. By seeing graphs of CPU usage over time we hope to correlate
# that with possible improvements to Rust's own build system, ideally diagnosing
# that either builders are always fully using their CPU resources or they're
# idle for long stretches of time.
#
# This script is relatively simple, but it's platform specific. Each platform
# (OSX/Windows/Linux) has a different way of calculating the current state of
# CPU at a point in time. We then compare two captured states to determine the
# percentage of time spent in one state versus another. The state capturing is
# all platform-specific but the loop at the bottom is the cross platform part
# that executes everywhere.
#
# # Viewing statistics
#
# All builders will upload their CPU statistics as CSV files to our S3 buckets.
# These URLS look like:
#
# https://$bucket.s3.amazonaws.com/rustc-builds/$commit/cpu-$builder.csv
#
# for example
#
# https://rust-lang-ci2.s3.amazonaws.com/rustc-builds/68baada19cd5340f05f0db15a3e16d6671609bcc/cpu-x86_64-apple.csv
#
# Each CSV file has two columns. The first is the timestamp of the measurement
# and the second column is the % of idle cpu time in that time slice. Ideally
# the second column is always zero.
#
# Once you've downloaded a file there's various ways to plot it and visualize
# it. For command line usage you can use a script like so:
#
# set timefmt '%Y-%m-%dT%H:%M:%S'
# set xdata time
# set ylabel "Idle CPU %"
# set xlabel "Time"
# set datafile sep ','
# set term png
# set output "printme.png"
# set grid
# builder = "i686-apple"
# plot "cpu-".builder.".csv" using 1:2 with lines title builder
#
# Executed as `gnuplot < ./foo.plot` it will generate a graph called
# `printme.png` which you can then open up. If you know how to improve this
# script or the viewing process that would be much appreciated :) (or even if
# you know how to automate it!)

import datetime
import sys
import time

if sys.platform == 'linux2':
class State:
def __init__(self):
with open('/proc/stat', 'r') as file:
data = file.readline().split()
if data[0] != 'cpu':
raise Exception('did not start with "cpu"')
self.user = int(data[1])
self.nice = int(data[2])
self.system = int(data[3])
self.idle = int(data[4])
self.iowait = int(data[5])
self.irq = int(data[6])
self.softirq = int(data[7])
self.steal = int(data[8])
self.guest = int(data[9])
self.guest_nice = int(data[10])

def idle_since(self, prev):
user = self.user - prev.user
nice = self.nice - prev.nice
system = self.system - prev.system
idle = self.idle - prev.idle
iowait = self.iowait - prev.iowait
irq = self.irq - prev.irq
softirq = self.softirq - prev.softirq
steal = self.steal - prev.steal
guest = self.guest - prev.guest
guest_nice = self.guest_nice - prev.guest_nice
total = user + nice + system + idle + iowait + irq + softirq + steal + guest + guest_nice
return float(idle) / float(total) * 100

elif sys.platform == 'win32':
from ctypes.wintypes import DWORD
from ctypes import Structure, windll, WinError, GetLastError, byref

class FILETIME(Structure):
_fields_ = [
("dwLowDateTime", DWORD),
("dwHighDateTime", DWORD),
]

class State:
def __init__(self):
idle, kernel, user = FILETIME(), FILETIME(), FILETIME()

success = windll.kernel32.GetSystemTimes(
byref(idle),
byref(kernel),
byref(user),
)

assert success, WinError(GetLastError())[1]

self.idle = (idle.dwHighDateTime << 32) | idle.dwLowDateTime
self.kernel = (kernel.dwHighDateTime << 32) | kernel.dwLowDateTime
self.user = (user.dwHighDateTime << 32) | user.dwLowDateTime

def idle_since(self, prev):
idle = self.idle - prev.idle
user = self.user - prev.user
kernel = self.kernel - prev.kernel
return float(idle) / float(user + kernel) * 100

elif sys.platform == 'darwin':
from ctypes import *
libc = cdll.LoadLibrary('/usr/lib/libc.dylib')

PROESSOR_CPU_LOAD_INFO = c_int(2)
CPU_STATE_USER = 0
CPU_STATE_SYSTEM = 1
CPU_STATE_IDLE = 2
CPU_STATE_NICE = 3
c_int_p = POINTER(c_int)

class State:
def __init__(self):
num_cpus_u = c_uint(0)
cpu_info = c_int_p()
cpu_info_cnt = c_int(0)
err = libc.host_processor_info(
libc.mach_host_self(),
PROESSOR_CPU_LOAD_INFO,
byref(num_cpus_u),
byref(cpu_info),
byref(cpu_info_cnt),
)
assert err == 0
self.user = 0
self.system = 0
self.idle = 0
self.nice = 0
cur = 0
while cur < cpu_info_cnt.value:
self.user += cpu_info[cur + CPU_STATE_USER]
self.system += cpu_info[cur + CPU_STATE_SYSTEM]
self.idle += cpu_info[cur + CPU_STATE_IDLE]
self.nice += cpu_info[cur + CPU_STATE_NICE]
cur += num_cpus_u.value

def idle_since(self, prev):
user = self.user - prev.user
system = self.system - prev.system
idle = self.idle - prev.idle
nice = self.nice - prev.nice
return float(idle) / float(user + system + idle + nice) * 100.0

else:
print('unknown platform', sys.platform)
sys.exit(1)

cur_state = State();
print("Time,Idle")
while True:
time.sleep(1);
next_state = State();
now = datetime.datetime.utcnow().isoformat()
idle = next_state.idle_since(cur_state)
print("%s,%s" % (now, idle))
sys.stdout.flush()
cur_state = next_state
2 changes: 1 addition & 1 deletion src/doc/rust-by-example
Submodule rust-by-example updated 77 files
+2 −2 src/attribute.md
+1 −1 src/attribute/cfg.md
+1 −1 src/compatibility.md
+1 −1 src/conversion.md
+1 −1 src/conversion/string.md
+1 −1 src/crates/lib.md
+2 −2 src/custom_types/constants.md
+3 −3 src/custom_types/enum.md
+1 −1 src/custom_types/enum/c_like.md
+2 −2 src/custom_types/enum/enum_use.md
+2 −2 src/custom_types/enum/testcase_linked_list.md
+2 −2 src/custom_types/structs.md
+1 −1 src/error/multiple_error_types/option_result.md
+1 −1 src/error/multiple_error_types/wrap_error.md
+1 −1 src/error/option_unwrap/and_then.md
+1 −1 src/error/option_unwrap/map.md
+1 −1 src/error/result.md
+1 −1 src/error/result/enter_question_mark.md
+1 −1 src/error/result/result_alias.md
+1 −1 src/flow_control/for.md
+2 −2 src/flow_control/if_let.md
+1 −1 src/flow_control/match/binding.md
+4 −4 src/flow_control/match/destructuring.md
+2 −2 src/flow_control/match/destructuring/destructure_enum.md
+1 −1 src/flow_control/match/destructuring/destructure_structures.md
+1 −1 src/flow_control/match/destructuring/destructure_tuple.md
+1 −1 src/flow_control/match/guard.md
+2 −2 src/flow_control/while_let.md
+1 −1 src/fn/closures/anonymity.md
+1 −1 src/fn/closures/capture.md
+2 −2 src/fn/closures/output_parameters.md
+1 −1 src/generics.md
+2 −2 src/generics/assoc_items/the_problem.md
+5 −5 src/generics/bounds.md
+1 −1 src/generics/bounds/testcase_empty.md
+2 −2 src/generics/gen_fn.md
+2 −2 src/generics/gen_trait.md
+3 −3 src/generics/impl.md
+2 −2 src/generics/multi_bounds.md
+1 −1 src/generics/new_types.md
+3 −3 src/generics/phantom.md
+8 −8 src/generics/phantom/testcase_units.md
+2 −2 src/generics/where.md
+1 −1 src/hello.md
+1 −1 src/hello/comment.md
+5 −5 src/hello/print.md
+2 −2 src/hello/print/print_debug.md
+5 −5 src/hello/print/print_display.md
+6 −6 src/hello/print/print_display/testcase_list.md
+24 −24 src/index.md
+3 −3 src/macros/syntax.md
+1 −1 src/mod/split.md
+2 −2 src/mod/struct_visibility.md
+3 −3 src/primitives.md
+1 −1 src/primitives/tuples.md
+1 −1 src/scope/borrow/mut.md
+4 −4 src/scope/lifetime/explicit.md
+2 −2 src/scope/lifetime/fn.md
+3 −3 src/scope/lifetime/lifetime_bounds.md
+1 −1 src/scope/lifetime/methods.md
+1 −1 src/scope/lifetime/static_lifetime.md
+1 −1 src/scope/lifetime/struct.md
+1 −1 src/scope/lifetime/trait.md
+1 −1 src/scope/move.md
+1 −1 src/scope/raii.md
+1 −1 src/std.md
+1 −1 src/std_misc.md
+1 −1 src/std_misc/fs.md
+6 −6 src/std_misc/threads/testcase_mapreduce.md
+4 −4 src/testing.md
+2 −2 src/testing/integration_testing.md
+4 −4 src/testing/unit_testing.md
+1 −1 src/trait/derive.md
+4 −4 src/types.md
+1 −1 src/types/alias.md
+3 −3 src/types/literals.md
+1 −1 src/unsafe.md
41 changes: 41 additions & 0 deletions src/libcore/iter/range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,19 @@ impl<A: Step> DoubleEndedIterator for ops::Range<A> {
None
}
}

#[inline]
fn nth_back(&mut self, n: usize) -> Option<A> {
if let Some(minus_n) = self.end.sub_usize(n) {
if minus_n > self.start {
self.end = minus_n.sub_one();
return Some(self.end.clone())
}
}

self.end = self.start.clone();
None
}
}

#[stable(feature = "fused", since = "1.26.0")]
Expand Down Expand Up @@ -438,6 +451,34 @@ impl<A: Step> DoubleEndedIterator for ops::RangeInclusive<A> {
})
}

#[inline]
fn nth_back(&mut self, n: usize) -> Option<A> {
self.compute_is_empty();
if self.is_empty.unwrap_or_default() {
return None;
}

if let Some(minus_n) = self.end.sub_usize(n) {
use crate::cmp::Ordering::*;

match minus_n.partial_cmp(&self.start) {
Some(Greater) => {
self.is_empty = Some(false);
self.end = minus_n.sub_one();
return Some(minus_n);
}
Some(Equal) => {
self.is_empty = Some(true);
return Some(minus_n);
}
_ => {}
}
}

self.is_empty = Some(true);
None
}

#[inline]
fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R where
Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B>
Expand Down
21 changes: 20 additions & 1 deletion src/libcore/option.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ use crate::pin::Pin;
// which basically means it must be `Option`.

/// The `Option` type. See [the module level documentation](index.html) for more.
#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
#[derive(Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
#[stable(feature = "rust1", since = "1.0.0")]
pub enum Option<T> {
/// No value
Expand Down Expand Up @@ -1040,6 +1040,25 @@ fn expect_failed(msg: &str) -> ! {
// Trait implementations
/////////////////////////////////////////////////////////////////////////////

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Clone> Clone for Option<T> {
#[inline]
fn clone(&self) -> Self {
match self {
Some(x) => Some(x.clone()),
None => None,
}
}

#[inline]
fn clone_from(&mut self, source: &Self) {
match (self, source) {
(Some(to), Some(from)) => to.clone_from(from),
(to, from) => *to = from.clone(),
}
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Default for Option<T> {
/// Returns [`None`][Option::None].
Expand Down
23 changes: 22 additions & 1 deletion src/libcore/result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ use crate::ops::{self, Deref};
///
/// [`Ok`]: enum.Result.html#variant.Ok
/// [`Err`]: enum.Result.html#variant.Err
#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
#[derive(Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
#[must_use = "this `Result` may be an `Err` variant, which should be handled"]
#[stable(feature = "rust1", since = "1.0.0")]
pub enum Result<T, E> {
Expand Down Expand Up @@ -1003,6 +1003,27 @@ fn unwrap_failed<E: fmt::Debug>(msg: &str, error: E) -> ! {
// Trait implementations
/////////////////////////////////////////////////////////////////////////////

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Clone, E: Clone> Clone for Result<T, E> {
#[inline]
fn clone(&self) -> Self {
match self {
Ok(x) => Ok(x.clone()),
Err(x) => Err(x.clone()),
}
}

#[inline]
fn clone_from(&mut self, source: &Self) {
match (self, source) {
(Ok(to), Ok(from)) => to.clone_from(from),
(Err(to), Err(from)) => to.clone_from(from),
(to, from) => *to = from.clone(),
}
}
}


#[stable(feature = "rust1", since = "1.0.0")]
impl<T, E> IntoIterator for Result<T, E> {
type Item = T;
Expand Down
Loading

0 comments on commit c4797fa

Please sign in to comment.