( info_map: &HashMap<blake3::Hash, SubtermInfo>, topo_order: &[blake3::Hash], )
| 412 | /// Returns a summary of why sharing may not be effective. |
| 413 | #[allow(dead_code)] |
| 414 | pub fn analyze_sharing_stats( |
| 415 | info_map: &HashMap<blake3::Hash, SubtermInfo>, |
| 416 | topo_order: &[blake3::Hash], |
| 417 | ) -> SharingStats { |
| 418 | let effective_sizes = compute_effective_sizes(info_map, topo_order); |
| 419 | |
| 420 | let total_subterms = info_map.len(); |
| 421 | let mut usage_distribution: HashMap<usize, usize> = HashMap::new(); |
| 422 | let mut size_distribution: HashMap<usize, usize> = HashMap::new(); |
| 423 | let mut total_usage: usize = 0; |
| 424 | let mut unique_subterms = 0; |
| 425 | let mut shared_subterms = 0; |
| 426 | |
| 427 | for (hash, info) in info_map.iter() { |
| 428 | total_usage += info.usage_count; |
| 429 | *usage_distribution.entry(info.usage_count).or_insert(0) += 1; |
| 430 | |
| 431 | let size = effective_sizes.get(hash).copied().unwrap_or(0); |
| 432 | let size_bucket = match size { |
| 433 | 0..=1 => 1, |
| 434 | 2..=4 => 4, |
| 435 | 5..=10 => 10, |
| 436 | 11..=50 => 50, |
| 437 | 51..=100 => 100, |
| 438 | _ => 1000, |
| 439 | }; |
| 440 | *size_distribution.entry(size_bucket).or_insert(0) += 1; |
| 441 | |
| 442 | if info.usage_count == 1 { |
| 443 | unique_subterms += 1; |
| 444 | } else { |
| 445 | shared_subterms += 1; |
| 446 | } |
| 447 | } |
| 448 | |
| 449 | // Count candidates at each filtering stage |
| 450 | let candidates_usage_ge_2: usize = |
| 451 | info_map.values().filter(|info| info.usage_count >= 2).count(); |
| 452 | |
| 453 | let candidates_positive_potential: usize = info_map |
| 454 | .iter() |
| 455 | .filter(|(_, info)| info.usage_count >= 2) |
| 456 | .filter(|(hash, info)| { |
| 457 | let term_size = effective_sizes.get(hash).copied().unwrap_or(0); |
| 458 | let n = info.usage_count; |
| 459 | let potential = (n as isize - 1) * (term_size as isize) - (n as isize); |
| 460 | potential > 0 |
| 461 | }) |
| 462 | .count(); |
| 463 | |
| 464 | // Simulate actual sharing to count how many pass |
| 465 | let mut simulated_shared = 0; |
| 466 | let mut candidates: Vec<_> = info_map |
| 467 | .iter() |
| 468 | .filter(|(_, info)| info.usage_count >= 2) |
| 469 | .filter_map(|(hash, info)| { |
| 470 | let term_size = *effective_sizes.get(hash)?; |
| 471 | let n = info.usage_count; |
no test coverage detected