Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add compile-time option for logging Alloy stats #147

Merged
merged 1 commit into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions library/alloc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,6 @@ compiler-builtins-c = ["compiler_builtins/c"]
compiler-builtins-no-asm = ["compiler_builtins/no-asm"]
compiler-builtins-mangled-names = ["compiler_builtins/mangled-names"]
compiler-builtins-weak-intrinsics = ["compiler_builtins/weak-intrinsics"]
log-alloy-stats = []
# Make panics and failed asserts immediately abort without formatting any message
panic_immediate_abort = []
26 changes: 26 additions & 0 deletions library/alloc/src/alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,32 @@ pub use core::alloc::*;
#[cfg(test)]
mod tests;

#[cfg(feature = "log-alloy-stats")]
use core::sync::atomic::AtomicU64;

#[cfg(feature = "log-alloy-stats")]
#[unstable(feature = "gc", issue = "none")]
/// Global counters for various GC stats.
pub static GC_COUNTERS: GcCounters = GcCounters {
finalizers_registered: AtomicU64::new(0),
allocated_gc: AtomicU64::new(0),
allocated_boxed: AtomicU64::new(0),
allocated_rc: AtomicU64::new(0),
allocated_arc: AtomicU64::new(0),
};

#[cfg(feature = "log-alloy-stats")]
#[unstable(feature = "gc", issue = "none")]
#[allow(missing_docs)]
#[derive(Debug, Default)]
pub struct GcCounters {
pub finalizers_registered: AtomicU64,
pub allocated_gc: AtomicU64,
pub allocated_boxed: AtomicU64,
pub allocated_rc: AtomicU64,
pub allocated_arc: AtomicU64,
}

extern "Rust" {
// These are the magic symbols to call the global allocator. rustc generates
// them to call `__rg_alloc` etc. if there is a `#[global_allocator]` attribute
Expand Down
16 changes: 16 additions & 0 deletions library/alloc/src/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,12 @@ use crate::string::String;
#[cfg(not(no_global_oom_handling))]
use crate::vec::Vec;

#[cfg(feature = "log-alloy-stats")]
use crate::alloc::GC_COUNTERS;

#[cfg(feature = "log-alloy-stats")]
use core::sync::atomic;

#[cfg(test)]
mod tests;

Expand Down Expand Up @@ -392,6 +398,10 @@ impl<T> Rc<T> {
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new(value: T) -> Rc<T> {
#[cfg(feature = "log-alloy-stats")]
GC_COUNTERS.allocated_rc.fetch_add(1, atomic::Ordering::Relaxed);
#[cfg(feature = "log-alloy-stats")]
GC_COUNTERS.allocated_boxed.fetch_sub(1, atomic::Ordering::Relaxed);
// There is an implicit weak pointer owned by all the strong
// pointers, which ensures that the weak destructor never frees
// the allocation while the strong destructor is running, even
Expand Down Expand Up @@ -522,6 +532,12 @@ impl<T> Rc<T> {
#[unstable(feature = "new_uninit", issue = "63291")]
#[must_use]
pub fn new_uninit() -> Rc<mem::MaybeUninit<T>> {
#[cfg(feature = "log-alloy-stats")]
{
GC_COUNTERS.allocated_rc.fetch_add(1, atomic::Ordering::Relaxed);
// Decrement because `Rc` uses the global allocator.
GC_COUNTERS.allocated_boxed.fetch_sub(1, atomic::Ordering::Relaxed);
}
unsafe {
Rc::from_ptr(Rc::allocate_for_layout(
Layout::new::<T>(),
Expand Down
13 changes: 13 additions & 0 deletions library/alloc/src/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ use crate::string::String;
#[cfg(not(no_global_oom_handling))]
use crate::vec::Vec;

#[cfg(feature = "log-alloy-stats")]
use crate::alloc::GC_COUNTERS;

#[cfg(test)]
mod tests;

Expand Down Expand Up @@ -714,6 +717,12 @@ impl<T, A: Allocator> Arc<T, A> {
pub fn new_in(data: T, alloc: A) -> Arc<T, A> {
// Start the weak pointer count as 1 which is the weak pointer that's
// held by all the strong pointers (kinda), see std/rc.rs for more info
#[cfg(feature = "log-alloy-stats")]
{
GC_COUNTERS.allocated_arc.fetch_add(1, Relaxed);
// Decrement because `Arc` uses the global allocator.
GC_COUNTERS.allocated_boxed.fetch_sub(1, Relaxed);
}
let x = Box::new_in(
ArcInner {
strong: atomic::AtomicUsize::new(1),
Expand Down Expand Up @@ -754,6 +763,10 @@ impl<T, A: Allocator> Arc<T, A> {
// #[unstable(feature = "new_uninit", issue = "63291")]
#[inline]
pub fn new_uninit_in(alloc: A) -> Arc<mem::MaybeUninit<T>, A> {
#[cfg(feature = "log-alloy-stats")]
GC_COUNTERS.allocated_arc.fetch_add(1, atomic::Ordering::Relaxed);
#[cfg(feature = "log-alloy-stats")]
GC_COUNTERS.allocated_boxed.fetch_sub(1, atomic::Ordering::Relaxed);
unsafe {
Arc::from_ptr_in(
Arc::allocate_for_layout(
Expand Down
2 changes: 2 additions & 0 deletions library/std/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ backtrace = [
]
gimli-symbolize = []

log-alloy-stats = ["alloc/log-alloy-stats"]

panic-unwind = ["panic_unwind"]
profiler = ["profiler_builtins"]
compiler-builtins-c = ["alloc/compiler-builtins-c"]
Expand Down
54 changes: 22 additions & 32 deletions library/std/src/gc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,41 +56,15 @@ use core::slice::from_raw_parts_mut;

pub use core::gc::*;

#[cfg(profile_gc)]
use core::sync::atomic::{self, AtomicU64};
#[cfg(feature = "log-alloy-stats")]
use core::sync::atomic;

use core::sync::atomic::{self, AtomicU64};
#[cfg(feature = "log-alloy-stats")]
use crate::alloc::GC_COUNTERS;

#[cfg(test)]
mod tests;

#[derive(Default)]
struct GcCounters {
finalizers_registered: AtomicU64,
allocated_gc: AtomicU64,
allocated_normal: AtomicU64,
}

#[derive(Debug, Copy, Clone)]
pub struct GcStats {
pub finalizers_registered: u64,
pub finalizers_completed: u64,
pub allocated_gc: u64,
pub allocated_normal: u64,
pub num_gcs: u64,
}

static GC_COUNTERS: GcCounters = GcCounters {
finalizers_registered: AtomicU64::new(0),
allocated_gc: AtomicU64::new(0),
allocated_normal: AtomicU64::new(0),
};

#[cfg(profile_gc)]
static FINALIZERS_REGISTERED: AtomicU64 = AtomicU64::new(0);
#[cfg(profile_gc)]
static FINALIZERS_COMPLETED: AtomicU64 = AtomicU64::new(0);

////////////////////////////////////////////////////////////////////////////////
// BDWGC Allocator
////////////////////////////////////////////////////////////////////////////////
Expand All @@ -104,7 +78,6 @@ pub struct GcAllocator;
unsafe impl GlobalAlloc for GcAllocator {
#[inline]
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
GC_COUNTERS.allocated_normal.fetch_add(1, atomic::Ordering::Relaxed);
unsafe { gc_malloc(layout) }
}

Expand Down Expand Up @@ -164,6 +137,7 @@ unsafe fn gc_free(ptr: *mut u8, _: Layout) {
unsafe impl Allocator for GcAllocator {
#[inline]
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
#[cfg(feature = "log-alloy-stats")]
GC_COUNTERS.allocated_gc.fetch_add(1, atomic::Ordering::Relaxed);
match layout.size() {
0 => Ok(NonNull::slice_from_raw_parts(layout.dangling(), 0)),
Expand All @@ -184,15 +158,30 @@ impl GcAllocator {
}
}

#[cfg(feature = "log-alloy-stats")]
#[derive(Debug, Copy, Clone)]
pub struct GcStats {
pub finalizers_registered: u64,
pub finalizers_completed: u64,
pub allocated_gc: u64,
pub allocated_boxed: u64,
pub allocated_arc: u64,
pub allocated_rc: u64,
pub num_gcs: u64,
}

////////////////////////////////////////////////////////////////////////////////
// Free functions
////////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "log-alloy-stats")]
pub fn stats() -> GcStats {
GcStats {
finalizers_registered: GC_COUNTERS.finalizers_registered.load(atomic::Ordering::Relaxed),
finalizers_completed: unsafe { bdwgc::GC_finalized_total() },
allocated_gc: GC_COUNTERS.allocated_gc.load(atomic::Ordering::Relaxed),
allocated_normal: GC_COUNTERS.allocated_normal.load(atomic::Ordering::Relaxed),
allocated_boxed: GC_COUNTERS.allocated_boxed.load(atomic::Ordering::Relaxed),
allocated_rc: GC_COUNTERS.allocated_rc.load(atomic::Ordering::Relaxed),
allocated_arc: GC_COUNTERS.allocated_arc.load(atomic::Ordering::Relaxed),
num_gcs: unsafe { bdwgc::GC_get_gc_no() },
}
}
Expand Down Expand Up @@ -530,6 +519,7 @@ impl<T> Gc<T> {
ptr::null_mut(),
);
}
#[cfg(feature = "log-alloy-stats")]
GC_COUNTERS.finalizers_registered.fetch_add(1, atomic::Ordering::Relaxed);
Self::from_inner(ptr.into())
}
Expand Down
4 changes: 4 additions & 0 deletions library/std/src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2015,6 +2015,8 @@ impl ExitCode {
/// ```
#[unstable(feature = "exitcode_exit_method", issue = "97100")]
pub fn exit_process(self) -> ! {
#[cfg(feature = "log-alloy-stats")]
crate::rt::log_stats();
exit(self.to_i32())
}
}
Expand Down Expand Up @@ -2287,6 +2289,8 @@ impl Child {
#[cfg_attr(not(test), rustc_diagnostic_item = "process_exit")]
pub fn exit(code: i32) -> ! {
crate::rt::cleanup();
#[cfg(feature = "log-alloy-stats")]
crate::rt::log_stats();
crate::sys::os::exit(code)
}

Expand Down
30 changes: 30 additions & 0 deletions library/std/src/rt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,34 @@ unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
}
}

#[cfg(feature = "log-alloy-stats")]
pub(crate) fn log_stats() {
if crate::env::var("ALLOY_LOG").is_err() {
return;
}

use crate::io::Write;
let mut filename = crate::fs::OpenOptions::new()
.write(true)
.create(true)
.append(true)
.open(crate::env::var("ALLOY_LOG").unwrap())
.unwrap();

let headers =
"finalizers registered,finalizers completed,GC allocated,boxed allocated,GC cycles";
let stats = crate::gc::stats();
let stats = format!(
"{},{},{},{},{}\n",
stats.finalizers_registered,
stats.finalizers_completed,
stats.allocated_gc,
stats.allocated_boxed,
stats.num_gcs
);
write!(filename, "{}", format!("{headers}\n{stats}")).unwrap();
}

// One-time runtime cleanup.
// Runs after `main` or at program exit.
// NOTE: this is not guaranteed to run, for example when the program aborts.
Expand Down Expand Up @@ -170,5 +198,7 @@ fn lang_start<T: crate::process::Termination + 'static>(
argv,
sigpipe,
);
#[cfg(feature = "log-alloy-stats")]
crate::rt::log_stats();
v
}
1 change: 1 addition & 0 deletions library/sysroot/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ compiler-builtins-no-asm = ["std/compiler-builtins-no-asm"]
compiler-builtins-mangled-names = ["std/compiler-builtins-mangled-names"]
compiler-builtins-weak-intrinsics = ["std/compiler-builtins-weak-intrinsics"]
llvm-libunwind = ["std/llvm-libunwind"]
log-alloy-stats = ["std/log-alloy-stats"]
system-llvm-libunwind = ["std/system-llvm-libunwind"]
panic-unwind = ["std/panic_unwind"]
panic_immediate_abort = ["std/panic_immediate_abort"]
Expand Down
6 changes: 6 additions & 0 deletions src/bootstrap/src/core/config/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,8 @@ pub struct Config {
// libstd features
pub backtrace: bool, // support for RUST_BACKTRACE

pub log_alloy_stats: bool, // support for LOG_ALLOY_STATS

// misc
pub low_priority: bool,
pub channel: String,
Expand Down Expand Up @@ -1090,6 +1092,7 @@ define_config! {
debuginfo_level_tests: Option<DebuginfoLevel> = "debuginfo-level-tests",
split_debuginfo: Option<String> = "split-debuginfo",
backtrace: Option<bool> = "backtrace",
log_alloy_stats: Option<bool> = "log-alloy-stats",
incremental: Option<bool> = "incremental",
parallel_compiler: Option<bool> = "parallel-compiler",
default_linker: Option<String> = "default-linker",
Expand Down Expand Up @@ -1167,6 +1170,7 @@ impl Config {
ninja_in_file: true,
llvm_static_stdcpp: false,
backtrace: true,
log_alloy_stats: false,
rust_optimize: RustOptimize::Bool(true),
rust_optimize_tests: true,
submodules: None,
Expand Down Expand Up @@ -1575,6 +1579,7 @@ impl Config {
debuginfo_level_tests: debuginfo_level_tests_toml,
split_debuginfo,
backtrace,
log_alloy_stats,
incremental,
parallel_compiler,
default_linker,
Expand Down Expand Up @@ -1669,6 +1674,7 @@ impl Config {
set(&mut config.jemalloc, jemalloc);
set(&mut config.test_compare_mode, test_compare_mode);
set(&mut config.backtrace, backtrace);
set(&mut config.log_alloy_stats, log_alloy_stats);
config.description = description;
set(&mut config.rust_dist_src, dist_src);
set(&mut config.verbose_tests, verbose_tests);
Expand Down
3 changes: 3 additions & 0 deletions src/bootstrap/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -740,6 +740,9 @@ impl Build {
if self.config.backtrace {
features.push_str(" backtrace");
}
if self.config.log_alloy_stats {
features.push_str(" log-alloy-stats");
}
if self.config.profiler_enabled(target) {
features.push_str(" profiler");
}
Expand Down