Expand description
Custom global allocator which doesn’t assume 32 KiB heap size and offers mutable global state support.
§solana-allocator
A custom Solana allocator with the following features:
-
Supports heaps of arbitrary size. Default Solana allocator assumes 32 KiB of available space regardless of heap size configured via the
ComputeBudgetInstruction. This allocator will use all the allotted space. -
Supports opportunistic freeing and resizing. The default Solana allocator never frees memory and calling
msg!in a loop will eventually exhaust all memory. This allocator frees at least the last allocated object addressing simple case of temporary buffers. -
Allows declaring mutable global variables which is something Solana Virtual Machine doesn’t normally support. (Any program with mutable static variable will fail to deploy). This allocator offers a way to define such state.
§Usage
The crate provides custom_heap and custom_global macros which make use of
the allocator relatively straightforward. Note however, that
solana_program::entrypoint and anchor::program macros define global
allocator of their own unless custom-heap Cargo feature is enabled.
§Simple usage
For a simple usage (without support for mutable static variables), add the
dependency and use custom_heap macro. First in Cargo.toml:
[dependencies.solana-allocator]
name = "solana-allocator"
version = "0.1"
optional = true
[features]
default = ["custom-heap"]
custom-heap = ["dep:solana-allocator"]And than in lib.rs:
#[cfg(feature = "custom-heap")]
solana_allocator::custom_heap();§Usage with mutable global variables
For usage with the mutable global variables, additional bytemuck dependency
must be added and custom_global macro used instead. First in Cargo.toml:
[dependencies.bytemuck]
version = "*"
optional = true
[dependencies.solana-allocator]
name = "solana-allocator"
version = "0.1"
optional = true
[features]
default = ["custom-heap"]
custom-heap = ["dep:bytemuck", "dep:solana-allocator"]And then in lib.rs, for example:
solana_allocator::custom_global!(struct GlobalData {
counter: Cell<usize>,
});
#[cfg(target_os = "solana")]
pub fn unique() -> usize {
let counter = &global().counter;
let value = counter.get();
counter.set(value + 1);
value
}
#[cfg(not(target_os = "solana"))]
pub fn unique() -> usize {
use std::sync::atomic::{AtomicUsize, Ordering};
static COUNTER: AtomicUsize = AtomicUsize::new(0);
COUNTER.fetch_add(1, Ordering::SeqCst)
}See documentation or Mutable global state in Solana article for more detailed description.
Macros§
- custom_
global - On Solana, defines
BumpAllocatoras the global allocator with given global state. - custom_
heap - On Solana, defines
BumpAllocatoras the global allocator.