tinymist_analysis/
stats.rs1use std::sync::atomic::{AtomicUsize, Ordering};
4
5#[derive(Debug, Default)]
8pub struct AllocStats {
9 pub allocated: AtomicUsize,
11 pub dropped: AtomicUsize,
13}
14
15impl AllocStats {
16 pub fn increment(&self) {
18 self.allocated.fetch_add(1, Ordering::Relaxed);
19 }
20
21 pub fn decrement(&self) {
23 self.dropped.fetch_add(1, Ordering::Relaxed);
24 }
25
26 pub fn report() -> String {
28 let maps = crate::adt::interner::MAPS.lock().clone();
29 let mut data = Vec::new();
30 for (name, sz, map) in maps {
31 let allocated = map.allocated.load(std::sync::atomic::Ordering::Relaxed);
32 let dropped = map.dropped.load(std::sync::atomic::Ordering::Relaxed);
33 let alive = allocated.saturating_sub(dropped);
34 data.push((name, sz * alive, allocated, dropped, alive));
35 }
36
37 data.sort_by(|x, y| y.4.cmp(&x.4));
39
40 let mut html = String::new();
43 html.push_str(r#"<div>
44<style>
45table.alloc-stats { width: 100%; border-collapse: collapse; }
46table.alloc-stats th, table.alloc-stats td { border: 1px solid black; padding: 8px; text-align: center; }
47table.alloc-stats th.name-column, table.alloc-stats td.name-column { text-align: left; }
48table.alloc-stats tr:nth-child(odd) { background-color: rgba(242, 242, 242, 0.8); }
49@media (prefers-color-scheme: dark) {
50 table.alloc-stats tr:nth-child(odd) { background-color: rgba(50, 50, 50, 0.8); }
51}
52</style>
53<table class="alloc-stats"><tr><th class="name-column">Name</th><th>Alive</th><th>Allocated</th><th>Dropped</th><th>Size</th></tr>"#);
54
55 for (name, sz, allocated, dropped, alive) in data {
56 html.push_str("<tr>");
57 html.push_str(&format!(r#"<td class="name-column">{name}</td>"#));
58 html.push_str(&format!("<td>{alive}</td>"));
59 html.push_str(&format!("<td>{allocated}</td>"));
60 html.push_str(&format!("<td>{dropped}</td>"));
61 html.push_str(&format!("<td>{}</td>", human_size(sz)));
62 html.push_str("</tr>");
63 }
64 html.push_str("</table>");
65 html.push_str("</div>");
66
67 html
68 }
69}
70
71fn human_size(size: usize) -> String {
72 let units = ["B", "KB", "MB", "GB", "TB"];
73 let mut unit = 0;
74 let mut size = size as f64;
75 while size >= 768.0 && unit < units.len() {
76 size /= 1024.0;
77 unit += 1;
78 }
79 format!("{:.2} {}", size, units[unit])
80}