Is there any way to find the current amount of stack and heap usage in a solana program? I'm hitting stack AND heap limitations :(
1 Answer
If you are running out of heap you can use a custom allocator, here is one similar to the Solana implementation:
pub struct BumpAllocator {
pub start: usize,
pub len: usize,
}
impl BumpAllocator {
const RESERVED_MEM: usize = 1 * size_of::<*mut u8>();
/// Return heap position as of this call
pub unsafe fn pos(&self) -> usize {
let pos_ptr = self.start as *mut usize;
*pos_ptr
}
/// Reset heap start cursor to position.
/// ### This is very unsafe, use wisely
pub unsafe fn move_cursor(&self, pos: usize) {
let pos_ptr = self.start as *mut usize;
*pos_ptr = pos;
}
}
unsafe impl std::alloc::GlobalAlloc for BumpAllocator {
#[inline]
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
let pos_ptr = self.start as *mut usize;
let mut pos = *pos_ptr;
if pos == 0 {
// First time, set starting position
pos = self.start + self.len;
}
pos = pos.saturating_sub(layout.size());
pos &= !(layout.align().wrapping_sub(1));
if pos < self.start + BumpAllocator::RESERVED_MEM {
return null_mut();
}
*pos_ptr = pos;
pos as *mut u8
}
#[inline]
unsafe fn dealloc(&self, _: *mut u8, _: Layout) {
// no dellaoc in Solana runtime :*(
}
}
#[global_allocator]
static A: BumpAllocator = BumpAllocator {
start: HEAP_START_ADDRESS as usize,
len: HEAP_LENGTH,
};
Now you can read the heap's pointer to see what byte you are at, or to reset the heap pointer back to an earlier point:
let heap_start = unsafe { A.pos() };
msg!("heap ptr: {:?}", heap_start);
some_big_heap_function();
unsafe { A.move_cursor(heap_start); }