mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-28 17:53:56 +00:00
Add metrics for unevaluated constants, failed mir bodies, and failed data layouts
This commit is contained in:
parent
cbd14e9840
commit
51e8b8ff14
@ -2,7 +2,6 @@
|
|||||||
//! errors.
|
//! errors.
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
|
||||||
env,
|
env,
|
||||||
time::{SystemTime, UNIX_EPOCH},
|
time::{SystemTime, UNIX_EPOCH},
|
||||||
};
|
};
|
||||||
@ -16,7 +15,7 @@ use hir_def::{
|
|||||||
hir::{ExprId, PatId},
|
hir::{ExprId, PatId},
|
||||||
FunctionId,
|
FunctionId,
|
||||||
};
|
};
|
||||||
use hir_ty::{Interner, TyExt, TypeFlags};
|
use hir_ty::{Interner, Substitution, TyExt, TypeFlags};
|
||||||
use ide::{Analysis, AnalysisHost, LineCol, RootDatabase};
|
use ide::{Analysis, AnalysisHost, LineCol, RootDatabase};
|
||||||
use ide_db::base_db::{
|
use ide_db::base_db::{
|
||||||
salsa::{self, debug::DebugQueryTable, ParallelDatabase},
|
salsa::{self, debug::DebugQueryTable, ParallelDatabase},
|
||||||
@ -122,14 +121,19 @@ impl flags::AnalysisStats {
|
|||||||
eprint!(" crates: {num_crates}");
|
eprint!(" crates: {num_crates}");
|
||||||
let mut num_decls = 0;
|
let mut num_decls = 0;
|
||||||
let mut funcs = Vec::new();
|
let mut funcs = Vec::new();
|
||||||
|
let mut adts = Vec::new();
|
||||||
|
let mut consts = Vec::new();
|
||||||
while let Some(module) = visit_queue.pop() {
|
while let Some(module) = visit_queue.pop() {
|
||||||
if visited_modules.insert(module) {
|
if visited_modules.insert(module) {
|
||||||
visit_queue.extend(module.children(db));
|
visit_queue.extend(module.children(db));
|
||||||
|
|
||||||
for decl in module.declarations(db) {
|
for decl in module.declarations(db) {
|
||||||
num_decls += 1;
|
num_decls += 1;
|
||||||
if let ModuleDef::Function(f) = decl {
|
match decl {
|
||||||
funcs.push(f);
|
ModuleDef::Function(f) => funcs.push(f),
|
||||||
|
ModuleDef::Adt(a) => adts.push(a),
|
||||||
|
ModuleDef::Const(c) => consts.push(c),
|
||||||
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,10 +158,13 @@ impl flags::AnalysisStats {
|
|||||||
self.run_inference(&host, db, &vfs, &funcs, verbosity);
|
self.run_inference(&host, db, &vfs, &funcs, verbosity);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.mir_stats {
|
if !self.skip_mir_stats {
|
||||||
self.lower_mir(db, &funcs);
|
self.run_mir_lowering(db, &funcs, verbosity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.run_data_layout(db, &adts, verbosity);
|
||||||
|
self.run_const_eval(db, &consts, verbosity);
|
||||||
|
|
||||||
let total_span = analysis_sw.elapsed();
|
let total_span = analysis_sw.elapsed();
|
||||||
eprintln!("{:<20} {total_span}", "Total:");
|
eprintln!("{:<20} {total_span}", "Total:");
|
||||||
report_metric("total time", total_span.time.as_millis() as u64, "ms");
|
report_metric("total time", total_span.time.as_millis() as u64, "ms");
|
||||||
@ -193,22 +200,82 @@ impl flags::AnalysisStats {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_mir(&self, db: &RootDatabase, funcs: &[Function]) {
|
fn run_data_layout(&self, db: &RootDatabase, adts: &[hir::Adt], verbosity: Verbosity) {
|
||||||
let all = funcs.len();
|
let mut all = 0;
|
||||||
let mut fail = 0;
|
let mut fail = 0;
|
||||||
let mut h: HashMap<String, usize> = HashMap::new();
|
for &a in adts {
|
||||||
for f in funcs {
|
if db.generic_params(a.into()).iter().next().is_some() {
|
||||||
let f = FunctionId::from(*f);
|
// Data types with generics don't have layout.
|
||||||
let Err(e) = db.mir_body(f.into()) else {
|
continue;
|
||||||
|
}
|
||||||
|
all += 1;
|
||||||
|
let Err(e) = db.layout_of_adt(hir_def::AdtId::from(a).into(), Substitution::empty(Interner)) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
let es = format!("{:?}", e);
|
if verbosity.is_spammy() {
|
||||||
*h.entry(es).or_default() += 1;
|
let full_name = a
|
||||||
|
.module(db)
|
||||||
|
.path_to_root(db)
|
||||||
|
.into_iter()
|
||||||
|
.rev()
|
||||||
|
.filter_map(|it| it.name(db))
|
||||||
|
.chain(Some(a.name(db)))
|
||||||
|
.join("::");
|
||||||
|
println!("Data layout for {full_name} failed due {e:?}");
|
||||||
|
}
|
||||||
|
fail += 1;
|
||||||
|
}
|
||||||
|
eprintln!("Failed data layouts: {fail} ({}%)", fail * 100 / all);
|
||||||
|
report_metric("failed data layouts", fail, "#");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_const_eval(&self, db: &RootDatabase, consts: &[hir::Const], verbosity: Verbosity) {
|
||||||
|
let mut all = 0;
|
||||||
|
let mut fail = 0;
|
||||||
|
for &c in consts {
|
||||||
|
all += 1;
|
||||||
|
let Err(e) = c.render_eval(db) else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
if verbosity.is_spammy() {
|
||||||
|
let full_name = c
|
||||||
|
.module(db)
|
||||||
|
.path_to_root(db)
|
||||||
|
.into_iter()
|
||||||
|
.rev()
|
||||||
|
.filter_map(|it| it.name(db))
|
||||||
|
.chain(c.name(db))
|
||||||
|
.join("::");
|
||||||
|
println!("Const eval for {full_name} failed due {e:?}");
|
||||||
|
}
|
||||||
|
fail += 1;
|
||||||
|
}
|
||||||
|
eprintln!("Failed const evals: {fail} ({}%)", fail * 100 / all);
|
||||||
|
report_metric("failed const evals", fail, "#");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_mir_lowering(&self, db: &RootDatabase, funcs: &[Function], verbosity: Verbosity) {
|
||||||
|
let all = funcs.len() as u64;
|
||||||
|
let mut fail = 0;
|
||||||
|
for f in funcs {
|
||||||
|
let Err(e) = db.mir_body(FunctionId::from(*f).into()) else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
if verbosity.is_spammy() {
|
||||||
|
let full_name = f
|
||||||
|
.module(db)
|
||||||
|
.path_to_root(db)
|
||||||
|
.into_iter()
|
||||||
|
.rev()
|
||||||
|
.filter_map(|it| it.name(db))
|
||||||
|
.chain(Some(f.name(db)))
|
||||||
|
.join("::");
|
||||||
|
println!("Mir body for {full_name} failed due {e:?}");
|
||||||
|
}
|
||||||
fail += 1;
|
fail += 1;
|
||||||
}
|
}
|
||||||
let h = h.into_iter().sorted_by_key(|x| x.1).collect::<Vec<_>>();
|
|
||||||
eprintln!("Mir failed reasons: {:#?}", h);
|
|
||||||
eprintln!("Mir failed bodies: {fail} ({}%)", fail * 100 / all);
|
eprintln!("Mir failed bodies: {fail} ({}%)", fail * 100 / all);
|
||||||
|
report_metric("mir failed bodies", fail, "#");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_inference(
|
fn run_inference(
|
||||||
|
@ -66,8 +66,8 @@ xflags::xflags! {
|
|||||||
optional --memory-usage
|
optional --memory-usage
|
||||||
/// Print the total length of all source and macro files (whitespace is not counted).
|
/// Print the total length of all source and macro files (whitespace is not counted).
|
||||||
optional --source-stats
|
optional --source-stats
|
||||||
/// Print the number of bodies that fail to lower to mir, in addition to failed reasons.
|
/// Only type check, skip lowering to mir
|
||||||
optional --mir-stats
|
optional --skip-mir-stats
|
||||||
|
|
||||||
/// Only analyze items matching this path.
|
/// Only analyze items matching this path.
|
||||||
optional -o, --only path: String
|
optional -o, --only path: String
|
||||||
@ -171,7 +171,7 @@ pub struct AnalysisStats {
|
|||||||
pub parallel: bool,
|
pub parallel: bool,
|
||||||
pub memory_usage: bool,
|
pub memory_usage: bool,
|
||||||
pub source_stats: bool,
|
pub source_stats: bool,
|
||||||
pub mir_stats: bool,
|
pub skip_mir_stats: bool,
|
||||||
pub only: Option<String>,
|
pub only: Option<String>,
|
||||||
pub with_deps: bool,
|
pub with_deps: bool,
|
||||||
pub no_sysroot: bool,
|
pub no_sysroot: bool,
|
||||||
|
Loading…
Reference in New Issue
Block a user