diff options
-rw-r--r-- | crates/ra_prof/src/memory_usage.rs | 6 | ||||
-rw-r--r-- | crates/rust-analyzer/src/cli.rs | 7 | ||||
-rw-r--r-- | crates/rust-analyzer/src/cli/analysis_stats.rs | 59 | ||||
-rw-r--r-- | crates/rust-analyzer/src/lib.rs | 2 | ||||
-rw-r--r-- | xtask/src/metrics.rs | 55 | ||||
-rw-r--r-- | xtask/src/not_bash.rs | 3 |
6 files changed, 102 insertions, 30 deletions
diff --git a/crates/ra_prof/src/memory_usage.rs b/crates/ra_prof/src/memory_usage.rs index ee79ec3ee..745345fac 100644 --- a/crates/ra_prof/src/memory_usage.rs +++ b/crates/ra_prof/src/memory_usage.rs | |||
@@ -31,6 +31,12 @@ impl fmt::Display for MemoryUsage { | |||
31 | #[derive(Default, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)] | 31 | #[derive(Default, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)] |
32 | pub struct Bytes(usize); | 32 | pub struct Bytes(usize); |
33 | 33 | ||
34 | impl Bytes { | ||
35 | pub fn megabytes(self) -> usize { | ||
36 | self.0 / 1024 / 1024 | ||
37 | } | ||
38 | } | ||
39 | |||
34 | impl fmt::Display for Bytes { | 40 | impl fmt::Display for Bytes { |
35 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | 41 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
36 | let bytes = self.0; | 42 | let bytes = self.0; |
diff --git a/crates/rust-analyzer/src/cli.rs b/crates/rust-analyzer/src/cli.rs index 753001949..a9b9c8923 100644 --- a/crates/rust-analyzer/src/cli.rs +++ b/crates/rust-analyzer/src/cli.rs | |||
@@ -74,3 +74,10 @@ fn read_stdin() -> Result<String> { | |||
74 | std::io::stdin().read_to_string(&mut buff)?; | 74 | std::io::stdin().read_to_string(&mut buff)?; |
75 | Ok(buff) | 75 | Ok(buff) |
76 | } | 76 | } |
77 | |||
78 | fn report_metric(metric: &str, value: u64, unit: &str) { | ||
79 | if std::env::var("RA_METRICS").is_err() { | ||
80 | return; | ||
81 | } | ||
82 | println!("METRIC:{}:{}:{}", metric, value, unit) | ||
83 | } | ||
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs index ddb3db6c3..10327ebb9 100644 --- a/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/crates/rust-analyzer/src/cli/analysis_stats.rs | |||
@@ -3,26 +3,27 @@ | |||
3 | 3 | ||
4 | use std::{path::Path, time::Instant}; | 4 | use std::{path::Path, time::Instant}; |
5 | 5 | ||
6 | use itertools::Itertools; | ||
7 | use rand::{seq::SliceRandom, thread_rng}; | ||
8 | use rayon::prelude::*; | ||
9 | use rustc_hash::FxHashSet; | ||
10 | |||
11 | use hir::{ | 6 | use hir::{ |
12 | db::{AstDatabase, DefDatabase, HirDatabase}, | 7 | db::{AstDatabase, DefDatabase, HirDatabase}, |
13 | original_range, AssocItem, Crate, HasSource, HirDisplay, ModuleDef, | 8 | original_range, AssocItem, Crate, HasSource, HirDisplay, ModuleDef, |
14 | }; | 9 | }; |
15 | use hir_def::FunctionId; | 10 | use hir_def::FunctionId; |
16 | use hir_ty::{Ty, TypeWalk}; | 11 | use hir_ty::{Ty, TypeWalk}; |
12 | use itertools::Itertools; | ||
17 | use ra_db::{ | 13 | use ra_db::{ |
18 | salsa::{self, ParallelDatabase}, | 14 | salsa::{self, ParallelDatabase}, |
19 | SourceDatabaseExt, | 15 | SourceDatabaseExt, |
20 | }; | 16 | }; |
21 | use ra_syntax::AstNode; | 17 | use ra_syntax::AstNode; |
18 | use rand::{seq::SliceRandom, thread_rng}; | ||
19 | use rayon::prelude::*; | ||
20 | use rustc_hash::FxHashSet; | ||
22 | use stdx::format_to; | 21 | use stdx::format_to; |
23 | 22 | ||
24 | use crate::{ | 23 | use crate::{ |
25 | cli::{load_cargo::load_cargo, progress_report::ProgressReport, Result, Verbosity}, | 24 | cli::{ |
25 | load_cargo::load_cargo, progress_report::ProgressReport, report_metric, Result, Verbosity, | ||
26 | }, | ||
26 | print_memory_usage, | 27 | print_memory_usage, |
27 | }; | 28 | }; |
28 | 29 | ||
@@ -48,7 +49,7 @@ pub fn analysis_stats( | |||
48 | let db_load_time = Instant::now(); | 49 | let db_load_time = Instant::now(); |
49 | let (host, vfs) = load_cargo(path, load_output_dirs, with_proc_macro)?; | 50 | let (host, vfs) = load_cargo(path, load_output_dirs, with_proc_macro)?; |
50 | let db = host.raw_database(); | 51 | let db = host.raw_database(); |
51 | println!("Database loaded {:?}", db_load_time.elapsed()); | 52 | eprintln!("Database loaded {:?}", db_load_time.elapsed()); |
52 | let analysis_time = Instant::now(); | 53 | let analysis_time = Instant::now(); |
53 | let mut num_crates = 0; | 54 | let mut num_crates = 0; |
54 | let mut visited_modules = FxHashSet::default(); | 55 | let mut visited_modules = FxHashSet::default(); |
@@ -74,7 +75,7 @@ pub fn analysis_stats( | |||
74 | visit_queue.shuffle(&mut thread_rng()); | 75 | visit_queue.shuffle(&mut thread_rng()); |
75 | } | 76 | } |
76 | 77 | ||
77 | println!("Crates in this dir: {}", num_crates); | 78 | eprintln!("Crates in this dir: {}", num_crates); |
78 | let mut num_decls = 0; | 79 | let mut num_decls = 0; |
79 | let mut funcs = Vec::new(); | 80 | let mut funcs = Vec::new(); |
80 | while let Some(module) = visit_queue.pop() { | 81 | while let Some(module) = visit_queue.pop() { |
@@ -98,10 +99,15 @@ pub fn analysis_stats( | |||
98 | } | 99 | } |
99 | } | 100 | } |
100 | } | 101 | } |
101 | println!("Total modules found: {}", visited_modules.len()); | 102 | eprintln!("Total modules found: {}", visited_modules.len()); |
102 | println!("Total declarations: {}", num_decls); | 103 | eprintln!("Total declarations: {}", num_decls); |
103 | println!("Total functions: {}", funcs.len()); | 104 | eprintln!("Total functions: {}", funcs.len()); |
104 | println!("Item Collection: {:?}, {}", analysis_time.elapsed(), ra_prof::memory_usage()); | 105 | let item_collection_memory = ra_prof::memory_usage(); |
106 | eprintln!( | ||
107 | "Item Collection: {:?}, {}", | ||
108 | analysis_time.elapsed(), | ||
109 | item_collection_memory.allocated | ||
110 | ); | ||
105 | 111 | ||
106 | if randomize { | 112 | if randomize { |
107 | funcs.shuffle(&mut thread_rng()); | 113 | funcs.shuffle(&mut thread_rng()); |
@@ -123,7 +129,11 @@ pub fn analysis_stats( | |||
123 | snap.0.infer(f_id.into()); | 129 | snap.0.infer(f_id.into()); |
124 | }) | 130 | }) |
125 | .count(); | 131 | .count(); |
126 | println!("Parallel Inference: {:?}, {}", inference_time.elapsed(), ra_prof::memory_usage()); | 132 | eprintln!( |
133 | "Parallel Inference: {:?}, {}", | ||
134 | inference_time.elapsed(), | ||
135 | ra_prof::memory_usage().allocated | ||
136 | ); | ||
127 | } | 137 | } |
128 | 138 | ||
129 | let inference_time = Instant::now(); | 139 | let inference_time = Instant::now(); |
@@ -260,20 +270,31 @@ pub fn analysis_stats( | |||
260 | bar.inc(1); | 270 | bar.inc(1); |
261 | } | 271 | } |
262 | bar.finish_and_clear(); | 272 | bar.finish_and_clear(); |
263 | println!("Total expressions: {}", num_exprs); | 273 | eprintln!("Total expressions: {}", num_exprs); |
264 | println!( | 274 | eprintln!( |
265 | "Expressions of unknown type: {} ({}%)", | 275 | "Expressions of unknown type: {} ({}%)", |
266 | num_exprs_unknown, | 276 | num_exprs_unknown, |
267 | if num_exprs > 0 { num_exprs_unknown * 100 / num_exprs } else { 100 } | 277 | if num_exprs > 0 { num_exprs_unknown * 100 / num_exprs } else { 100 } |
268 | ); | 278 | ); |
269 | println!( | 279 | eprintln!( |
270 | "Expressions of partially unknown type: {} ({}%)", | 280 | "Expressions of partially unknown type: {} ({}%)", |
271 | num_exprs_partially_unknown, | 281 | num_exprs_partially_unknown, |
272 | if num_exprs > 0 { num_exprs_partially_unknown * 100 / num_exprs } else { 100 } | 282 | if num_exprs > 0 { num_exprs_partially_unknown * 100 / num_exprs } else { 100 } |
273 | ); | 283 | ); |
274 | println!("Type mismatches: {}", num_type_mismatches); | 284 | eprintln!("Type mismatches: {}", num_type_mismatches); |
275 | println!("Inference: {:?}, {}", inference_time.elapsed(), ra_prof::memory_usage()); | 285 | |
276 | println!("Total: {:?}, {}", analysis_time.elapsed(), ra_prof::memory_usage()); | 286 | let inference_time = inference_time.elapsed(); |
287 | let total_memory = ra_prof::memory_usage(); | ||
288 | eprintln!( | ||
289 | "Inference: {:?}, {}", | ||
290 | inference_time, | ||
291 | total_memory.allocated - item_collection_memory.allocated | ||
292 | ); | ||
293 | |||
294 | let analysis_time = analysis_time.elapsed(); | ||
295 | eprintln!("Total: {:?}, {}", analysis_time, total_memory); | ||
296 | report_metric("total time", analysis_time.as_millis() as u64, "ms"); | ||
297 | report_metric("total memory", total_memory.allocated.megabytes() as u64, "MB"); | ||
277 | 298 | ||
278 | if memory_usage { | 299 | if memory_usage { |
279 | print_memory_usage(host, vfs); | 300 | print_memory_usage(host, vfs); |
diff --git a/crates/rust-analyzer/src/lib.rs b/crates/rust-analyzer/src/lib.rs index c4284556e..ed37992cd 100644 --- a/crates/rust-analyzer/src/lib.rs +++ b/crates/rust-analyzer/src/lib.rs | |||
@@ -86,6 +86,6 @@ fn print_memory_usage(mut host: AnalysisHost, vfs: Vfs) { | |||
86 | mem.push(("Remaining".into(), ra_prof::memory_usage().allocated)); | 86 | mem.push(("Remaining".into(), ra_prof::memory_usage().allocated)); |
87 | 87 | ||
88 | for (name, bytes) in mem { | 88 | for (name, bytes) in mem { |
89 | println!("{:>8} {}", bytes, name); | 89 | eprintln!("{:>8} {}", bytes, name); |
90 | } | 90 | } |
91 | } | 91 | } |
diff --git a/xtask/src/metrics.rs b/xtask/src/metrics.rs index 6c042d695..9ac3fa51d 100644 --- a/xtask/src/metrics.rs +++ b/xtask/src/metrics.rs | |||
@@ -3,14 +3,15 @@ use std::{ | |||
3 | env, | 3 | env, |
4 | fmt::{self, Write as _}, | 4 | fmt::{self, Write as _}, |
5 | io::Write as _, | 5 | io::Write as _, |
6 | path::Path, | ||
6 | time::{Instant, SystemTime, UNIX_EPOCH}, | 7 | time::{Instant, SystemTime, UNIX_EPOCH}, |
7 | }; | 8 | }; |
8 | 9 | ||
9 | use anyhow::{bail, format_err, Result}; | 10 | use anyhow::{bail, format_err, Result}; |
10 | 11 | ||
11 | use crate::not_bash::{fs2, pushd, rm_rf, run}; | 12 | use crate::not_bash::{fs2, pushd, pushenv, rm_rf, run}; |
12 | 13 | ||
13 | type Unit = &'static str; | 14 | type Unit = String; |
14 | 15 | ||
15 | pub struct MetricsCmd { | 16 | pub struct MetricsCmd { |
16 | pub dry_run: bool, | 17 | pub dry_run: bool, |
@@ -22,9 +23,21 @@ impl MetricsCmd { | |||
22 | if !self.dry_run { | 23 | if !self.dry_run { |
23 | rm_rf("./target/release")?; | 24 | rm_rf("./target/release")?; |
24 | } | 25 | } |
26 | if !Path::new("./target/rustc-perf").exists() { | ||
27 | fs2::create_dir_all("./target/rustc-perf")?; | ||
28 | run!("git clone https://github.com/rust-lang/rustc-perf.git ./target/rustc-perf")?; | ||
29 | } | ||
30 | { | ||
31 | let _d = pushd("./target/rustc-perf"); | ||
32 | run!("git reset --hard 1d9288b0da7febf2599917da1b57dc241a1af033")?; | ||
33 | } | ||
34 | |||
35 | let _env = pushenv("RA_METRICS", "1"); | ||
25 | 36 | ||
26 | metrics.measure_build()?; | 37 | metrics.measure_build()?; |
27 | metrics.measure_analysis_stats_self()?; | 38 | metrics.measure_analysis_stats_self()?; |
39 | metrics.measure_analysis_stats("ripgrep")?; | ||
40 | metrics.measure_analysis_stats("webrender")?; | ||
28 | 41 | ||
29 | if !self.dry_run { | 42 | if !self.dry_run { |
30 | let _d = pushd("target"); | 43 | let _d = pushd("target"); |
@@ -46,23 +59,47 @@ impl MetricsCmd { | |||
46 | 59 | ||
47 | impl Metrics { | 60 | impl Metrics { |
48 | fn measure_build(&mut self) -> Result<()> { | 61 | fn measure_build(&mut self) -> Result<()> { |
62 | eprintln!("\nMeasuring build"); | ||
49 | run!("cargo fetch")?; | 63 | run!("cargo fetch")?; |
50 | 64 | ||
51 | let time = Instant::now(); | 65 | let time = Instant::now(); |
52 | run!("cargo build --release --package rust-analyzer --bin rust-analyzer")?; | 66 | run!("cargo build --release --package rust-analyzer --bin rust-analyzer")?; |
53 | let time = time.elapsed(); | 67 | let time = time.elapsed(); |
54 | self.report("build", time.as_millis() as u64, "ms"); | 68 | self.report("build", time.as_millis() as u64, "ms".into()); |
55 | Ok(()) | 69 | Ok(()) |
56 | } | 70 | } |
57 | fn measure_analysis_stats_self(&mut self) -> Result<()> { | 71 | fn measure_analysis_stats_self(&mut self) -> Result<()> { |
58 | let time = Instant::now(); | 72 | self.measure_analysis_stats_path("self", &".") |
59 | run!("./target/release/rust-analyzer analysis-stats .")?; | 73 | } |
60 | let time = time.elapsed(); | 74 | fn measure_analysis_stats(&mut self, bench: &str) -> Result<()> { |
61 | self.report("analysis-stats/self", time.as_millis() as u64, "ms"); | 75 | self.measure_analysis_stats_path( |
76 | bench, | ||
77 | &format!("./target/rustc-perf/collector/benchmarks/{}", bench), | ||
78 | ) | ||
79 | } | ||
80 | fn measure_analysis_stats_path(&mut self, name: &str, path: &str) -> Result<()> { | ||
81 | eprintln!("\nMeasuring analysis-stats/{}", name); | ||
82 | let output = run!("./target/release/rust-analyzer analysis-stats --quiet {}", path)?; | ||
83 | for (metric, value, unit) in parse_metrics(&output) { | ||
84 | self.report(&format!("analysis-stats/{}/{}", name, metric), value, unit.into()); | ||
85 | } | ||
62 | Ok(()) | 86 | Ok(()) |
63 | } | 87 | } |
64 | } | 88 | } |
65 | 89 | ||
90 | fn parse_metrics(output: &str) -> Vec<(&str, u64, &str)> { | ||
91 | output | ||
92 | .lines() | ||
93 | .filter_map(|it| { | ||
94 | let entry = it.split(':').collect::<Vec<_>>(); | ||
95 | match entry.as_slice() { | ||
96 | ["METRIC", name, value, unit] => Some((*name, value.parse().unwrap(), *unit)), | ||
97 | _ => None, | ||
98 | } | ||
99 | }) | ||
100 | .collect() | ||
101 | } | ||
102 | |||
66 | #[derive(Debug)] | 103 | #[derive(Debug)] |
67 | struct Metrics { | 104 | struct Metrics { |
68 | host: Host, | 105 | host: Host, |
@@ -111,11 +148,11 @@ impl Metrics { | |||
111 | json.field("metrics"); | 148 | json.field("metrics"); |
112 | json.begin_object(); | 149 | json.begin_object(); |
113 | { | 150 | { |
114 | for (k, &(value, unit)) in &self.metrics { | 151 | for (k, (value, unit)) in &self.metrics { |
115 | json.field(k); | 152 | json.field(k); |
116 | json.begin_array(); | 153 | json.begin_array(); |
117 | { | 154 | { |
118 | json.number(value as f64); | 155 | json.number(*value as f64); |
119 | json.string(unit); | 156 | json.string(unit); |
120 | } | 157 | } |
121 | json.end_array(); | 158 | json.end_array(); |
diff --git a/xtask/src/not_bash.rs b/xtask/src/not_bash.rs index 0f3a56b25..ef811e5bf 100644 --- a/xtask/src/not_bash.rs +++ b/xtask/src/not_bash.rs | |||
@@ -186,7 +186,8 @@ impl Env { | |||
186 | fn pushd(&mut self, dir: PathBuf) { | 186 | fn pushd(&mut self, dir: PathBuf) { |
187 | let dir = self.cwd().join(dir); | 187 | let dir = self.cwd().join(dir); |
188 | self.pushd_stack.push(dir); | 188 | self.pushd_stack.push(dir); |
189 | env::set_current_dir(self.cwd()).unwrap(); | 189 | env::set_current_dir(self.cwd()) |
190 | .unwrap_or_else(|err| panic!("Failed to set cwd to {}: {}", self.cwd().display(), err)); | ||
190 | } | 191 | } |
191 | fn popd(&mut self) { | 192 | fn popd(&mut self) { |
192 | self.pushd_stack.pop().unwrap(); | 193 | self.pushd_stack.pop().unwrap(); |