Skip to content

Commit 7204374

Browse files
committed
Report instructions in addition to time
They hopefully will be more stable on CI
1 parent 4bab553 commit 7204374

File tree

5 files changed

+115
-20
lines changed

5 files changed

+115
-20
lines changed

Cargo.lock

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/ra_prof/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ once_cell = "1.3.1"
1515
backtrace = { version = "0.3.44", optional = true }
1616
cfg-if = "0.1.10"
1717
libc = "0.2.73"
18+
perf-event = "0.4"
1819

1920
[features]
2021
cpu_profiler = []

crates/ra_prof/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! A collection of tools for profiling rust-analyzer.
22
3+
mod stop_watch;
34
mod memory_usage;
45
#[cfg(feature = "cpu_profiler")]
56
mod google_cpu_profiler;
@@ -11,6 +12,7 @@ use std::cell::RefCell;
1112
pub use crate::{
1213
hprof::{init, init_from, profile},
1314
memory_usage::{Bytes, MemoryUsage},
15+
stop_watch::{StopWatch, StopWatchSpan},
1416
};
1517

1618
/// Prints backtrace to stderr, useful for debugging.

crates/ra_prof/src/stop_watch.rs

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
use crate::MemoryUsage;
2+
use std::{
3+
fmt,
4+
time::{Duration, Instant},
5+
};
6+
7+
pub struct StopWatch {
8+
time: Instant,
9+
counter: Option<perf_event::Counter>,
10+
memory: Option<MemoryUsage>,
11+
}
12+
13+
pub struct StopWatchSpan {
14+
pub time: Duration,
15+
pub instructions: Option<u64>,
16+
pub memory: Option<MemoryUsage>,
17+
}
18+
19+
impl StopWatch {
20+
pub fn start() -> StopWatch {
21+
let mut counter = perf_event::Builder::new().build().ok();
22+
if let Some(counter) = &mut counter {
23+
let _ = counter.enable();
24+
}
25+
let time = Instant::now();
26+
StopWatch { time, counter, memory: None }
27+
}
28+
pub fn memory(mut self, yes: bool) -> StopWatch {
29+
if yes {
30+
self.memory = Some(MemoryUsage::current());
31+
}
32+
self
33+
}
34+
pub fn elapsed(&mut self) -> StopWatchSpan {
35+
let time = self.time.elapsed();
36+
let instructions = self.counter.as_mut().and_then(|it| it.read().ok());
37+
let memory = self.memory.map(|it| MemoryUsage::current() - it);
38+
StopWatchSpan { time, instructions, memory }
39+
}
40+
}
41+
42+
impl fmt::Display for StopWatchSpan {
43+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44+
write!(f, "{:.2?}", self.time)?;
45+
if let Some(mut instructions) = self.instructions {
46+
let mut prefix = "";
47+
if instructions > 10000 {
48+
instructions /= 1000;
49+
prefix = "k"
50+
}
51+
if instructions > 10000 {
52+
instructions /= 1000;
53+
prefix = "m"
54+
}
55+
write!(f, ", {}{}i", instructions, prefix)?;
56+
}
57+
if let Some(memory) = self.memory {
58+
write!(f, ", {}", memory)?;
59+
}
60+
Ok(())
61+
}
62+
}
63+
64+
// Unclear if we need this:
65+
// https://github.com/jimblandy/perf-event/issues/8
66+
impl Drop for StopWatch {
67+
fn drop(&mut self) {
68+
if let Some(mut counter) = self.counter.take() {
69+
let _ = counter.disable();
70+
}
71+
}
72+
}

crates/rust-analyzer/src/cli/analysis_stats.rs

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
44
use std::{
55
path::Path,
6-
time::{Instant, SystemTime, UNIX_EPOCH},
6+
time::{SystemTime, UNIX_EPOCH},
77
};
88

99
use hir::{
@@ -29,6 +29,7 @@ use crate::{
2929
},
3030
print_memory_usage,
3131
};
32+
use ra_prof::StopWatch;
3233

3334
/// Need to wrap Snapshot to provide `Clone` impl for `map_with`
3435
struct Snap<DB>(DB);
@@ -54,11 +55,12 @@ pub fn analysis_stats(
5455
Rand32::new(seed)
5556
};
5657

57-
let db_load_time = Instant::now();
58+
let mut db_load_sw = StopWatch::start().memory(memory_usage);
5859
let (host, vfs) = load_cargo(path, load_output_dirs, with_proc_macro)?;
5960
let db = host.raw_database();
60-
eprintln!("Database loaded {:?}", db_load_time.elapsed());
61-
let analysis_time = Instant::now();
61+
eprintln!("Database loaded {}", db_load_sw.elapsed());
62+
63+
let mut analysis_sw = StopWatch::start().memory(memory_usage);
6264
let mut num_crates = 0;
6365
let mut visited_modules = FxHashSet::default();
6466
let mut visit_queue = Vec::new();
@@ -110,8 +112,7 @@ pub fn analysis_stats(
110112
eprintln!("Total modules found: {}", visited_modules.len());
111113
eprintln!("Total declarations: {}", num_decls);
112114
eprintln!("Total functions: {}", funcs.len());
113-
let item_collection_memory = ra_prof::memory_usage();
114-
eprintln!("Item Collection: {:?}, {}", analysis_time.elapsed(), item_collection_memory);
115+
eprintln!("Item Collection: {}", analysis_sw.elapsed());
115116

116117
if randomize {
117118
shuffle(&mut rng, &mut funcs);
@@ -123,7 +124,7 @@ pub fn analysis_stats(
123124
};
124125

125126
if parallel {
126-
let inference_time = Instant::now();
127+
let mut inference_sw = StopWatch::start().memory(memory_usage);
127128
let snap = Snap(db.snapshot());
128129
funcs
129130
.par_iter()
@@ -133,14 +134,10 @@ pub fn analysis_stats(
133134
snap.0.infer(f_id.into());
134135
})
135136
.count();
136-
eprintln!(
137-
"Parallel Inference: {:?}, {}",
138-
inference_time.elapsed(),
139-
ra_prof::memory_usage()
140-
);
137+
eprintln!("Parallel Inference: {}", inference_sw.elapsed());
141138
}
142139

143-
let inference_time = Instant::now();
140+
let mut inference_sw = StopWatch::start().memory(memory_usage);
144141
bar.tick();
145142
let mut num_exprs = 0;
146143
let mut num_exprs_unknown = 0;
@@ -291,14 +288,17 @@ pub fn analysis_stats(
291288
eprintln!("Type mismatches: {}", num_type_mismatches);
292289
report_metric("type mismatches", num_type_mismatches, "#");
293290

294-
let inference_time = inference_time.elapsed();
295-
let total_memory = ra_prof::memory_usage();
296-
eprintln!("Inference: {:?}, {}", inference_time, total_memory - item_collection_memory);
291+
eprintln!("Inference: {}", inference_sw.elapsed());
297292

298-
let analysis_time = analysis_time.elapsed();
299-
eprintln!("Total: {:?}, {}", analysis_time, total_memory);
300-
report_metric("total time", analysis_time.as_millis() as u64, "ms");
301-
report_metric("total memory", total_memory.allocated.megabytes() as u64, "MB");
293+
let total_span = analysis_sw.elapsed();
294+
eprintln!("Total: {}", total_span);
295+
report_metric("total time", total_span.time.as_millis() as u64, "ms");
296+
if let Some(instructions) = total_span.instructions {
297+
report_metric("total time", instructions, "#instr");
298+
}
299+
if let Some(memory) = total_span.memory {
300+
report_metric("total memory", memory.allocated.megabytes() as u64, "MB");
301+
}
302302

303303
if memory_usage {
304304
print_memory_usage(host, vfs);

0 commit comments

Comments
 (0)