From 7204374719f4021ce06c25e7dd72b09a56923954 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 30 Jul 2020 09:44:21 +0200 Subject: Report instructions in addition to time They hopefully will be more stable on CI --- crates/ra_prof/src/stop_watch.rs | 72 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 crates/ra_prof/src/stop_watch.rs (limited to 'crates/ra_prof/src/stop_watch.rs') diff --git a/crates/ra_prof/src/stop_watch.rs b/crates/ra_prof/src/stop_watch.rs new file mode 100644 index 000000000..54bfb0559 --- /dev/null +++ b/crates/ra_prof/src/stop_watch.rs @@ -0,0 +1,72 @@ +use crate::MemoryUsage; +use std::{ + fmt, + time::{Duration, Instant}, +}; + +pub struct StopWatch { + time: Instant, + counter: Option, + memory: Option, +} + +pub struct StopWatchSpan { + pub time: Duration, + pub instructions: Option, + pub memory: Option, +} + +impl StopWatch { + pub fn start() -> StopWatch { + let mut counter = perf_event::Builder::new().build().ok(); + if let Some(counter) = &mut counter { + let _ = counter.enable(); + } + let time = Instant::now(); + StopWatch { time, counter, memory: None } + } + pub fn memory(mut self, yes: bool) -> StopWatch { + if yes { + self.memory = Some(MemoryUsage::current()); + } + self + } + pub fn elapsed(&mut self) -> StopWatchSpan { + let time = self.time.elapsed(); + let instructions = self.counter.as_mut().and_then(|it| it.read().ok()); + let memory = self.memory.map(|it| MemoryUsage::current() - it); + StopWatchSpan { time, instructions, memory } + } +} + +impl fmt::Display for StopWatchSpan { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:.2?}", self.time)?; + if let Some(mut instructions) = self.instructions { + let mut prefix = ""; + if instructions > 10000 { + instructions /= 1000; + prefix = "k" + } + if instructions > 10000 { + instructions /= 1000; + prefix = "m" + } + write!(f, ", {}{}i", instructions, prefix)?; + } + if let Some(memory) = self.memory { + write!(f, ", {}", memory)?; + } + Ok(()) + } +} + +// Unclear if we need this: +// https://github.com/jimblandy/perf-event/issues/8 +impl Drop for StopWatch { + fn drop(&mut self) { + if let Some(mut counter) = self.counter.take() { + let _ = counter.disable(); + } + } +} -- cgit v1.2.3 From 5e498546e8275c86e0b3f711b069b2787c6385f2 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 30 Jul 2020 10:40:55 +0200 Subject: Fix non-linux compilation --- crates/ra_prof/src/stop_watch.rs | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) (limited to 'crates/ra_prof/src/stop_watch.rs') diff --git a/crates/ra_prof/src/stop_watch.rs b/crates/ra_prof/src/stop_watch.rs index 54bfb0559..c52c92ce5 100644 --- a/crates/ra_prof/src/stop_watch.rs +++ b/crates/ra_prof/src/stop_watch.rs @@ -1,11 +1,13 @@ -use crate::MemoryUsage; use std::{ fmt, time::{Duration, Instant}, }; +use crate::MemoryUsage; + pub struct StopWatch { time: Instant, + #[cfg(target_os = "linux")] counter: Option, memory: Option, } @@ -18,12 +20,21 @@ pub struct StopWatchSpan { impl StopWatch { pub fn start() -> StopWatch { - let mut counter = perf_event::Builder::new().build().ok(); - if let Some(counter) = &mut counter { - let _ = counter.enable(); - } + #[cfg(target_os = "linux")] + let counter = { + let mut counter = perf_event::Builder::new().build().ok(); + if let Some(counter) = &mut counter { + let _ = counter.enable(); + } + counter + }; let time = Instant::now(); - StopWatch { time, counter, memory: None } + StopWatch { + time, + #[cfg(target_os = "linux")] + counter, + memory: None, + } } pub fn memory(mut self, yes: bool) -> StopWatch { if yes { @@ -33,7 +44,12 @@ impl StopWatch { } pub fn elapsed(&mut self) -> StopWatchSpan { let time = self.time.elapsed(); + + #[cfg(target_os = "linux")] let instructions = self.counter.as_mut().and_then(|it| it.read().ok()); + #[cfg(not(target_os = "linux"))] + let instructions = None; + let memory = self.memory.map(|it| MemoryUsage::current() - it); StopWatchSpan { time, instructions, memory } } @@ -65,6 +81,7 @@ impl fmt::Display for StopWatchSpan { // https://github.com/jimblandy/perf-event/issues/8 impl Drop for StopWatch { fn drop(&mut self) { + #[cfg(target_os = "linux")] if let Some(mut counter) = self.counter.take() { let _ = counter.disable(); } -- cgit v1.2.3 From f22af66c3763c4b2a9d16621473cb6979fb2f36d Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 30 Jul 2020 10:43:47 +0200 Subject: Fixes --- crates/ra_prof/src/stop_watch.rs | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'crates/ra_prof/src/stop_watch.rs') diff --git a/crates/ra_prof/src/stop_watch.rs b/crates/ra_prof/src/stop_watch.rs index c52c92ce5..8b8ec25a5 100644 --- a/crates/ra_prof/src/stop_watch.rs +++ b/crates/ra_prof/src/stop_watch.rs @@ -1,3 +1,4 @@ +//! Like `std::time::Instant`, but also measures memory & CPU cycles. use std::{ fmt, time::{Duration, Instant}, @@ -76,14 +77,3 @@ impl fmt::Display for StopWatchSpan { Ok(()) } } - -// Unclear if we need this: -// https://github.com/jimblandy/perf-event/issues/8 -impl Drop for StopWatch { - fn drop(&mut self) { - #[cfg(target_os = "linux")] - if let Some(mut counter) = self.counter.take() { - let _ = counter.disable(); - } - } -} -- cgit v1.2.3 From 3e1e6227ca525f8631e0bff2215fa3de1b4f4cc1 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 30 Jul 2020 14:27:19 +0200 Subject: Print errors when failing to create a perf counter --- crates/ra_prof/src/stop_watch.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'crates/ra_prof/src/stop_watch.rs') diff --git a/crates/ra_prof/src/stop_watch.rs b/crates/ra_prof/src/stop_watch.rs index 8b8ec25a5..5e276190e 100644 --- a/crates/ra_prof/src/stop_watch.rs +++ b/crates/ra_prof/src/stop_watch.rs @@ -23,9 +23,14 @@ impl StopWatch { pub fn start() -> StopWatch { #[cfg(target_os = "linux")] let counter = { - let mut counter = perf_event::Builder::new().build().ok(); + let mut counter = perf_event::Builder::new() + .build() + .map_err(|err| eprintln!("Failed to create perf counter: {}", err)) + .ok(); if let Some(counter) = &mut counter { - let _ = counter.enable(); + if let Err(err) = counter.enable() { + eprintln!("Failed to start perf counter: {}", err) + } } counter }; @@ -47,7 +52,9 @@ impl StopWatch { let time = self.time.elapsed(); #[cfg(target_os = "linux")] - let instructions = self.counter.as_mut().and_then(|it| it.read().ok()); + let instructions = self.counter.as_mut().and_then(|it| { + it.read().map_err(|err| eprintln!("Failed to read perf counter: {}", err)).ok() + }); #[cfg(not(target_os = "linux"))] let instructions = None; -- cgit v1.2.3