Skip to main content

luaur_repl_cli/functions/
profiler_dump.rs

1//! Faithful port of `void profilerDump(const char* path)` (CLI/src/Profiler.cpp:115).
2
3use alloc::collections::BTreeMap;
4use core::ffi::{c_char, c_int, CStr};
5use core::sync::atomic::Ordering;
6use std::io::Write;
7
8use luaur_vm::functions::lua_c_statename::luaC_statename;
9
10use crate::functions::profiler_trigger::G_PROFILER;
11
12pub fn profiler_dump(path: *const c_char) {
13    unsafe {
14        if path.is_null() {
15            return;
16        }
17        let path_str = CStr::from_ptr(path).to_string_lossy().into_owned();
18        let profiler = core::ptr::addr_of_mut!(G_PROFILER).as_mut().unwrap();
19
20        let mut f = match std::fs::File::create(&path_str) {
21            Ok(f) => f,
22            Err(_) => {
23                eprintln!("Error opening profile {}", path_str);
24                return;
25            }
26        };
27
28        let mut total: u64 = 0;
29        let data = profiler.data.get_or_insert_with(BTreeMap::new);
30        for (stack, &ticks) in data.iter() {
31            // C++: fprintf(f, "%lld %s\n", ticks, stack)
32            let _ = writeln!(f, "{} {}", ticks, stack);
33            total += ticks;
34        }
35        drop(f);
36
37        let stacks = data.len();
38        let samples = profiler.samples.load(Ordering::Relaxed);
39        println!(
40            "Profiler dump written to {} (total runtime {:.3} seconds, {} samples, {} stacks)",
41            path_str,
42            total as f64 / 1e6,
43            samples,
44            stacks
45        );
46
47        let mut totalgc: u64 = 0;
48        for &p in profiler.gc.iter() {
49            totalgc += p;
50        }
51
52        if totalgc != 0 {
53            print!(
54                "GC: {:.3} seconds ({:.2}%)",
55                totalgc as f64 / 1e6,
56                totalgc as f64 / total as f64 * 100.0
57            );
58
59            for i in 0..profiler.gc.len() {
60                let p = profiler.gc[i];
61                if p != 0 {
62                    let name_ptr = luaC_statename(i as c_int);
63                    let name = if name_ptr.is_null() {
64                        alloc::borrow::Cow::Borrowed("")
65                    } else {
66                        CStr::from_ptr(name_ptr).to_string_lossy()
67                    };
68                    print!(", {} {:.2}%", name, p as f64 / totalgc as f64 * 100.0);
69                }
70            }
71
72            println!();
73        }
74    }
75}