diff --git a/Cargo.lock b/Cargo.lock index 4f691f39e94..b26e2454c97 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1147,8 +1147,6 @@ dependencies = [ "fst 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "insta 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jemalloc-ctl 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jemallocator 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "join_to_string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "proptest 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1223,6 +1221,8 @@ dependencies = [ "backtrace 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)", "cpuprofiler 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jemalloc-ctl 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jemallocator 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "once_cell 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/crates/ra_cli/src/analysis_stats.rs b/crates/ra_cli/src/analysis_stats.rs index ed98fc7f655..2eaf784a6b9 100644 --- a/crates/ra_cli/src/analysis_stats.rs +++ b/crates/ra_cli/src/analysis_stats.rs @@ -112,6 +112,6 @@ pub fn run(verbose: bool, path: &Path, only: Option<&str>) -> Result<()> { num_exprs_partially_unknown, (num_exprs_partially_unknown * 100 / num_exprs) ); - println!("Analysis: {:?}", analysis_time.elapsed()); + println!("Analysis: {:?}, {}", analysis_time.elapsed(), ra_prof::memory_usage()); Ok(()) } diff --git a/crates/ra_ide_api/Cargo.toml b/crates/ra_ide_api/Cargo.toml index 9bf5dd6e662..5bd76881713 100644 --- a/crates/ra_ide_api/Cargo.toml +++ b/crates/ra_ide_api/Cargo.toml @@ -16,9 +16,6 @@ unicase = "2.2.0" superslice = "1.0.0" rand = "0.6.5" -jemallocator = { version = "0.1.9", optional = true } -jemalloc-ctl = { version = "0.2.0", optional = true } - ra_syntax = { path = "../ra_syntax" } ra_text_edit = { path = "../ra_text_edit" } ra_db = { path = "../ra_db" } @@ -36,6 +33,3 @@ version = "0.9.0" # Disable `fork` feature to allow compiling on webassembly default-features = false features = ["std", "bit-set", "break-dead-code"] - -[features] -jemalloc = [ "jemallocator", "jemalloc-ctl" ] diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs index e61d5627e00..28a74c003a6 100644 --- a/crates/ra_ide_api/src/lib.rs +++ b/crates/ra_ide_api/src/lib.rs @@ -74,12 +74,6 @@ pub use crate::{ pub use ra_db::{Canceled, CrateGraph, CrateId, FileId, FilePosition, FileRange, SourceRootId, Edition}; pub use hir::Documentation; -// We use jemalloc mainly to get heap usage statistics, actual performance -// difference is not measures. -#[cfg(feature = "jemalloc")] -#[global_allocator] -static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc; - pub type Cancelable = Result; #[derive(Debug)] diff --git a/crates/ra_ide_api/src/status.rs b/crates/ra_ide_api/src/status.rs index 0cdeb15eb73..ce25f4a875a 100644 --- a/crates/ra_ide_api/src/status.rs +++ b/crates/ra_ide_api/src/status.rs @@ -9,6 +9,7 @@ use ra_db::{ FileTextQuery, SourceRootId, salsa::{Database, debug::{DebugQueryTable, TableEntry}}, }; +use ra_prof::{Bytes, memory_usage}; use hir::MacroFile; use crate::{ @@ -34,7 +35,7 @@ pub(crate) fn status(db: &RootDatabase) -> String { symbols_stats, syntax_tree_stats, macro_syntax_tree_stats, - MemoryStats::current(), + memory_usage(), db.last_gc.elapsed().as_secs(), ) } @@ -138,54 +139,3 @@ impl FromIterator>> for LibrarySymbols res } } - -struct MemoryStats { - allocated: Bytes, - resident: Bytes, -} - -impl MemoryStats { - #[cfg(feature = "jemalloc")] - fn current() -> MemoryStats { - jemalloc_ctl::epoch().unwrap(); - MemoryStats { - allocated: Bytes(jemalloc_ctl::stats::allocated().unwrap()), - resident: Bytes(jemalloc_ctl::stats::resident().unwrap()), - } - } - - #[cfg(not(feature = "jemalloc"))] - fn current() -> MemoryStats { - MemoryStats { allocated: Bytes(0), resident: Bytes(0) } - } -} - -impl fmt::Display for MemoryStats { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "{} allocated {} resident", self.allocated, self.resident,) - } -} - -#[derive(Default)] -struct Bytes(usize); - -impl fmt::Display for Bytes { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let bytes = self.0; - if bytes < 4096 { - return write!(f, "{} bytes", bytes); - } - let kb = bytes / 1024; - if kb < 4096 { - return write!(f, "{}kb", kb); - } - let mb = kb / 1024; - write!(f, "{}mb", mb) - } -} - -impl std::ops::AddAssign for Bytes { - fn add_assign(&mut self, x: usize) { - self.0 += x; - } -} diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml index a1fcf6ceea8..4491b859001 100644 --- a/crates/ra_lsp_server/Cargo.toml +++ b/crates/ra_lsp_server/Cargo.toml @@ -32,4 +32,4 @@ tempfile = "3" test_utils = { path = "../test_utils" } [features] -jemalloc = [ "ra_ide_api/jemalloc" ] +jemalloc = [ "ra_prof/jemalloc" ] diff --git a/crates/ra_prof/Cargo.toml b/crates/ra_prof/Cargo.toml index 787e1838598..e986019ca90 100644 --- a/crates/ra_prof/Cargo.toml +++ b/crates/ra_prof/Cargo.toml @@ -10,3 +10,9 @@ once_cell = "0.2.0" itertools = "0.8.0" backtrace = "0.3.28" cpuprofiler = { version = "0.0.3", optional = true } +jemallocator = { version = "0.1.9", optional = true } +jemalloc-ctl = { version = "0.2.0", optional = true } + + +[features] +jemalloc = [ "jemallocator", "jemalloc-ctl" ] diff --git a/crates/ra_prof/src/lib.rs b/crates/ra_prof/src/lib.rs index 1e8d780ab60..6f79187456f 100644 --- a/crates/ra_prof/src/lib.rs +++ b/crates/ra_prof/src/lib.rs @@ -1,3 +1,5 @@ +mod memory_usage; + use std::{ cell::RefCell, time::{Duration, Instant}, @@ -11,6 +13,14 @@ use std::{ use once_cell::sync::Lazy; use itertools::Itertools; +pub use crate::memory_usage::{MemoryUsage, Bytes}; + +// We use jemalloc mainly to get heap usage statistics, actual performance +// difference is not measures. +#[cfg(feature = "jemalloc")] +#[global_allocator] +static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc; + /// Set profiling filter. It specifies descriptions allowed to profile. /// This is helpful when call stack has too many nested profiling scopes. /// Additionally filter can specify maximum depth of profiling scopes nesting. @@ -288,6 +298,10 @@ impl Drop for CpuProfiler { } } +pub fn memory_usage() -> MemoryUsage { + MemoryUsage::current() +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/ra_prof/src/memory_usage.rs b/crates/ra_prof/src/memory_usage.rs new file mode 100644 index 00000000000..2bde8fb5fba --- /dev/null +++ b/crates/ra_prof/src/memory_usage.rs @@ -0,0 +1,52 @@ +use std::fmt; + +pub struct MemoryUsage { + pub allocated: Bytes, + pub resident: Bytes, +} + +impl MemoryUsage { + #[cfg(feature = "jemalloc")] + pub fn current() -> MemoryUsage { + jemalloc_ctl::epoch().unwrap(); + MemoryUsage { + allocated: Bytes(jemalloc_ctl::stats::allocated().unwrap()), + resident: Bytes(jemalloc_ctl::stats::resident().unwrap()), + } + } + + #[cfg(not(feature = "jemalloc"))] + pub fn current() -> MemoryUsage { + MemoryUsage { allocated: Bytes(0), resident: Bytes(0) } + } +} + +impl fmt::Display for MemoryUsage { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "{} allocated {} resident", self.allocated, self.resident,) + } +} + +#[derive(Default)] +pub struct Bytes(usize); + +impl fmt::Display for Bytes { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let bytes = self.0; + if bytes < 4096 { + return write!(f, "{} bytes", bytes); + } + let kb = bytes / 1024; + if kb < 4096 { + return write!(f, "{}kb", kb); + } + let mb = kb / 1024; + write!(f, "{}mb", mb) + } +} + +impl std::ops::AddAssign for Bytes { + fn add_assign(&mut self, x: usize) { + self.0 += x; + } +}