use std::ffi::CStr;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MemoryBreakdownEntry {
pub buft_name: String,
pub model: usize,
pub context: usize,
pub compute: usize,
}
impl MemoryBreakdownEntry {
#[must_use]
pub fn total(&self) -> usize {
self.model + self.context + self.compute
}
}
fn raw_entry_to_rust(
entry: &llama_cpp_sys_4::llama_memory_breakdown_entry,
) -> MemoryBreakdownEntry {
let bytes: &[u8] = unsafe {
std::slice::from_raw_parts(entry.buft_name.as_ptr().cast(), entry.buft_name.len())
};
let name = CStr::from_bytes_until_nul(bytes)
.map(|c| c.to_string_lossy().into_owned())
.unwrap_or_default();
MemoryBreakdownEntry {
buft_name: name,
model: entry.model,
context: entry.context,
compute: entry.compute,
}
}
#[must_use]
pub(crate) fn collect_memory_breakdown(
ctx: *const llama_cpp_sys_4::llama_context,
) -> Vec<MemoryBreakdownEntry> {
if ctx.is_null() {
return Vec::new();
}
let mut capacity = 16usize;
loop {
let mut raw = vec![
llama_cpp_sys_4::llama_memory_breakdown_entry {
buft_name: [0; 128],
model: 0,
context: 0,
compute: 0,
};
capacity
];
let n = unsafe {
llama_cpp_sys_4::llama_memory_breakdown_collect(ctx, raw.as_mut_ptr(), capacity)
};
if n < capacity {
return raw
.into_iter()
.take(n)
.map(|e| raw_entry_to_rust(&e))
.collect();
}
capacity = capacity.saturating_mul(2);
if capacity > 4096 {
return raw.into_iter().map(|e| raw_entry_to_rust(&e)).collect();
}
}
}