From 1eff5a98f1c83f37ca2daac1c52f3eb84f395acd Mon Sep 17 00:00:00 2001 From: Maxime Chevalier-Boisvert Date: Tue, 28 May 2024 13:23:01 -0400 Subject: [PATCH] YJIT: limit size of call count stats dict (#10858) * YJIT: limit size of call count stats dict Someone reported that logs were getting bloated because the ISEQ and C call count dicts were huge, since they include all of the call sites. I wrote code on the Rust size to limit the size of the dict to avoid this problem. The size limit is hardcoded at 20, but I figure this is probably fine? * Fix bug reported by Kokubun. --- yjit/src/stats.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/yjit/src/stats.rs b/yjit/src/stats.rs index 6ffe28f12a..1f94c19398 100644 --- a/yjit/src/stats.rs +++ b/yjit/src/stats.rs @@ -802,16 +802,31 @@ fn rb_yjit_gen_stats_dict(context: bool) -> VALUE { rb_hash_aset(hash, key, value); } + // Set method call counts in a Ruby dict fn set_call_counts( calls_hash: VALUE, method_name_to_idx: &mut Option>, method_call_count: &mut Option>, ) { if let (Some(name_to_idx), Some(call_counts)) = (method_name_to_idx, method_call_count) { + // Create a list of (name, call_count) pairs + let mut pairs = Vec::new(); for (name, idx) in name_to_idx { let count = call_counts[*idx]; + pairs.push((name, count)); + } + + // Sort the vectors by decreasing call counts + pairs.sort_by_key(|e| -(e.1 as i64)); + + // Cap the number of counts reported to avoid + // bloating log files, etc. + pairs.truncate(20); + + // Add the pairs to the dict + for (name, call_count) in pairs { let key = rust_str_to_sym(name); - let value = VALUE::fixnum_from_usize(count as usize); + let value = VALUE::fixnum_from_usize(call_count as usize); unsafe { rb_hash_aset(calls_hash, key, value); } } }