Include countme crate to count important data structures.

This commit is contained in:
Aleksey Kladov 2021-01-21 19:04:50 +03:00
parent 235583f3fc
commit e5c5c0a040
9 changed files with 58 additions and 4 deletions

27
Cargo.lock generated
View file

@ -273,6 +273,17 @@ version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28b9d6de7f49e22cf97ad17fc4036ece69300032f45f78f30b4a4482cdc3f4a6" checksum = "28b9d6de7f49e22cf97ad17fc4036ece69300032f45f78f30b4a4482cdc3f4a6"
[[package]]
name = "countme"
version = "2.0.0-pre.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5716604cba7c02a846ecad3f4a3fd2d2b641faccc2a24a51efb21aff0d01f35"
dependencies = [
"dashmap",
"once_cell",
"rustc-hash",
]
[[package]] [[package]]
name = "crc32fast" name = "crc32fast"
version = "1.2.1" version = "1.2.1"
@ -349,6 +360,16 @@ dependencies = [
"lazy_static", "lazy_static",
] ]
[[package]]
name = "dashmap"
version = "4.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e77a43b28d0668df09411cb0bc9a8c2adc40f9a048afe863e05fd43251e8e39c"
dependencies = [
"cfg-if 1.0.0",
"num_cpus",
]
[[package]] [[package]]
name = "dissimilar" name = "dissimilar"
version = "1.0.2" version = "1.0.2"
@ -1260,6 +1281,7 @@ name = "profile"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"countme",
"jemalloc-ctl", "jemalloc-ctl",
"la-arena", "la-arena",
"libc", "libc",
@ -1375,10 +1397,11 @@ checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581"
[[package]] [[package]]
name = "rowan" name = "rowan"
version = "0.12.0" version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bea4527c692099becd37ec777cfd6949d0534348528d2fc84ee420d2d5fac83d" checksum = "24c2d78254049413f9d73495f883e7fa0b7a7d4b88468cd72a3bbbd0ad585cd1"
dependencies = [ dependencies = [
"countme",
"hashbrown", "hashbrown",
"memoffset", "memoffset",
"rustc-hash", "rustc-hash",

View file

@ -21,6 +21,7 @@ use hir_expand::{
HirFileId, InFile, HirFileId, InFile,
}; };
use la_arena::{Arena, Idx, RawIdx}; use la_arena::{Arena, Idx, RawIdx};
use profile::Count;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use smallvec::SmallVec; use smallvec::SmallVec;
use syntax::{ast, match_ast}; use syntax::{ast, match_ast};
@ -67,6 +68,8 @@ impl GenericParamsId {
/// The item tree of a source file. /// The item tree of a source file.
#[derive(Debug, Eq, PartialEq)] #[derive(Debug, Eq, PartialEq)]
pub struct ItemTree { pub struct ItemTree {
_c: Count<Self>,
top_level: SmallVec<[ModItem; 1]>, top_level: SmallVec<[ModItem; 1]>,
attrs: FxHashMap<AttrOwner, RawAttrs>, attrs: FxHashMap<AttrOwner, RawAttrs>,
@ -116,7 +119,12 @@ impl ItemTree {
} }
fn empty() -> Self { fn empty() -> Self {
Self { top_level: Default::default(), attrs: Default::default(), data: Default::default() } Self {
_c: Count::new(),
top_level: Default::default(),
attrs: Default::default(),
data: Default::default(),
}
} }
fn shrink_to_fit(&mut self) { fn shrink_to_fit(&mut self) {

View file

@ -59,6 +59,7 @@ use std::sync::Arc;
use base_db::{CrateId, Edition, FileId}; use base_db::{CrateId, Edition, FileId};
use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile}; use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile};
use la_arena::Arena; use la_arena::Arena;
use profile::Count;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use stdx::format_to; use stdx::format_to;
use syntax::{ast, AstNode}; use syntax::{ast, AstNode};
@ -75,6 +76,7 @@ use crate::{
/// Contains all top-level defs from a macro-expanded crate /// Contains all top-level defs from a macro-expanded crate
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub struct DefMap { pub struct DefMap {
_c: Count<Self>,
parent: Option<Arc<DefMap>>, parent: Option<Arc<DefMap>>,
root: LocalModuleId, root: LocalModuleId,
modules: Arena<ModuleData>, modules: Arena<ModuleData>,
@ -215,6 +217,7 @@ impl DefMap {
let mut modules: Arena<ModuleData> = Arena::default(); let mut modules: Arena<ModuleData> = Arena::default();
let root = modules.alloc(ModuleData::default()); let root = modules.alloc(ModuleData::default());
DefMap { DefMap {
_c: Count::new(),
parent: None, parent: None,
krate, krate,
edition, edition,

View file

@ -38,6 +38,7 @@ pub(crate) fn status(db: &RootDatabase, file_id: Option<FileId>) -> String {
format_to!(buf, "{}\n", syntax_tree_stats(db)); format_to!(buf, "{}\n", syntax_tree_stats(db));
format_to!(buf, "{} (macros)\n", macro_syntax_tree_stats(db)); format_to!(buf, "{} (macros)\n", macro_syntax_tree_stats(db));
format_to!(buf, "{} total\n", memory_usage()); format_to!(buf, "{} total\n", memory_usage());
format_to!(buf, "\ncounts:\n{}", profile::countme::get_all());
if let Some(file_id) = file_id { if let Some(file_id) = file_id {
format_to!(buf, "\nfile info:\n"); format_to!(buf, "\nfile info:\n");
@ -60,6 +61,7 @@ pub(crate) fn status(db: &RootDatabase, file_id: Option<FileId>) -> String {
None => format_to!(buf, "does not belong to any crate"), None => format_to!(buf, "does not belong to any crate"),
} }
} }
buf buf
} }

View file

@ -14,6 +14,7 @@ once_cell = "1.3.1"
cfg-if = "1" cfg-if = "1"
libc = "0.2.73" libc = "0.2.73"
la-arena = { version = "0.2.0", path = "../../lib/arena" } la-arena = { version = "0.2.0", path = "../../lib/arena" }
countme = { version = "2.0.0-pre.2", features = ["enable"] }
jemalloc-ctl = { version = "0.3.3", optional = true } jemalloc-ctl = { version = "0.3.3", optional = true }
[target.'cfg(target_os = "linux")'.dependencies] [target.'cfg(target_os = "linux")'.dependencies]

View file

@ -3,6 +3,7 @@ use once_cell::sync::Lazy;
use std::{ use std::{
cell::RefCell, cell::RefCell,
collections::{BTreeMap, HashSet}, collections::{BTreeMap, HashSet},
env,
io::{stderr, Write}, io::{stderr, Write},
sync::{ sync::{
atomic::{AtomicBool, Ordering}, atomic::{AtomicBool, Ordering},
@ -18,7 +19,8 @@ use crate::tree::{Idx, Tree};
/// env RA_PROFILE=foo|bar|baz // enabled only selected entries /// env RA_PROFILE=foo|bar|baz // enabled only selected entries
/// env RA_PROFILE=*@3>10 // dump everything, up to depth 3, if it takes more than 10 ms /// env RA_PROFILE=*@3>10 // dump everything, up to depth 3, if it takes more than 10 ms
pub fn init() { pub fn init() {
let spec = std::env::var("RA_PROFILE").unwrap_or_default(); countme::enable(env::var("RA_COUNT").is_ok());
let spec = env::var("RA_PROFILE").unwrap_or_default();
init_from(&spec); init_from(&spec);
} }

View file

@ -15,6 +15,13 @@ pub use crate::{
stop_watch::{StopWatch, StopWatchSpan}, stop_watch::{StopWatch, StopWatchSpan},
}; };
pub use countme;
/// Include `_c: Count<Self>` field in important structs to count them.
///
/// To view the counts, run with `RA_COUNT=1`. The overhead of disabled count is
/// almost zero.
pub use countme::Count;
thread_local!(static IN_SCOPE: RefCell<bool> = RefCell::new(false)); thread_local!(static IN_SCOPE: RefCell<bool> = RefCell::new(false));
/// Allows to check if the current code is withing some dynamic scope, can be /// Allows to check if the current code is withing some dynamic scope, can be

View file

@ -2,6 +2,7 @@
//! errors. //! errors.
use std::{ use std::{
env,
path::PathBuf, path::PathBuf,
time::{SystemTime, UNIX_EPOCH}, time::{SystemTime, UNIX_EPOCH},
}; };
@ -295,6 +296,10 @@ impl AnalysisStatsCmd {
report_metric("total memory", memory.allocated.megabytes() as u64, "MB"); report_metric("total memory", memory.allocated.megabytes() as u64, "MB");
} }
if env::var("RA_COUNT").is_ok() {
eprintln!("{}", profile::countme::get_all());
}
if self.memory_usage && verbosity.is_verbose() { if self.memory_usage && verbosity.is_verbose() {
print_memory_usage(host, vfs); print_memory_usage(host, vfs);
} }

View file

@ -251,6 +251,9 @@ RA_PROFILE=*@3>10 // dump everything, up to depth 3, if it takes more tha
In particular, I have `export RA_PROFILE='*>10'` in my shell profile. In particular, I have `export RA_PROFILE='*>10'` in my shell profile.
We also have a "counting" profiler which counts number of instances of popular structs.
It is enabled by `RA_COUNT=1`.
To measure time for from-scratch analysis, use something like this: To measure time for from-scratch analysis, use something like this:
``` ```