5 releases
| 0.0.4 | Nov 29, 2019 |
|---|---|
| 0.0.3 | Nov 3, 2019 |
| 0.0.2 | Feb 6, 2019 |
| 0.0.1 | Feb 6, 2019 |
| 0.0.0 | Feb 6, 2019 |
#272 in Memory management
883 downloads per month
Used in 17 crates
(16 directly)
16KB
170 lines
alloc_counter
Alloc counters
A redesign of the Quick and Dirty Allocation Profiling Tool.
Features
-
Although
#[no_std]is intended, it isn't currently supported due to the lack of portablethread_localimplementation. This may be "fixed" with a feature flag to use a global atomic under the contract that the program is single threaded. -
Count allocations, reallocations and deallocations individually with
count_alloc. -
Allow, deny, and forbid use of the global allocator with
allow_alloc,deny_allocandforbid_alloc. -
#[no_alloc]function attribute to deny and#[no_alloc(forbid)]to forbid use of the global allocator. -
#[count_alloc]function attribute to print the counts to stderr. Alternatively use#[count_alloc(func = "my_function")]wheremy_functionaccepts a triple ofusizes and returns()to redirect the output.
Limitations and known issues
-
Methods must either take a reference to
selforSelfmust be aCopytype. -
Ordinary and async functions must be treated differently. Use
count_allocfor functions andcount_alloc_futurefor futures.
Usage
An AllocCounter<A> wraps an allocator A to individually count the number of calls to
alloc, realloc, and dealloc.
use alloc_counter::AllocCounter;
type MyAllocator = std::alloc::System;
const MyAllocator: MyAllocator = std::alloc::System;
#[global_allocator]
static A: AllocCounter<MyAllocator> = AllocCounter(MyAllocator);
Std-users may prefer to inherit their system's allocator.
use alloc_counter::AllocCounterSystem;
#[global_allocator]
static A: AllocCounterSystem = AllocCounterSystem;
To count the allocations of an expression, use count_alloc.
# use alloc_counter::{count_alloc, AllocCounterSystem};
# #[global_allocator]
# static A: AllocCounterSystem = AllocCounterSystem;
let (counts, v) = count_alloc(|| {
// no alloc
let mut v = Vec::new();
// alloc
v.push(0);
// realloc
v.push(1);
// return the vector without deallocating
v
});
assert_eq!(counts, (1, 1, 0));
To deny allocations for an expression use deny_alloc.
# use alloc_counter::{deny_alloc, AllocCounterSystem};
# #[global_allocator]
# static A: AllocCounterSystem = AllocCounterSystem;
fn foo(b: Box<i32>) {
// dropping causes a panic
deny_alloc(|| drop(b))
}
foo(Box::new(0));
Similar to Rust's lints, you can still allow allocation inside a deny block.
# use alloc_counter::{allow_alloc, deny_alloc, AllocCounterSystem};
# #[global_allocator]
# static A: AllocCounterSystem = AllocCounterSystem;
fn foo(b: Box<i32>) {
deny_alloc(|| allow_alloc(|| drop(b)))
}
foo(Box::new(0));
Forbidding allocations forces a panic even when allow_alloc is used.
# use alloc_counter::{allow_alloc, forbid_alloc, AllocCounterSystem};
# #[global_allocator]
# static A: AllocCounterSystem = AllocCounterSystem;
fn foo(b: Box<i32>) {
// panics because of outer `forbid`, even though drop happens in an allow block
forbid_alloc(|| allow_alloc(|| drop(b)))
}
foo(Box::new(0));
For added sugar you may use the #[no_alloc] attribute on functions, including methods with
self-binds. #[no_alloc] expands to calling deny_alloc and forcefully moves the parameters
into the checked block. #[no_alloc(forbid)] calls forbid_alloc.
# #[cfg(not(feature = "macros"))]
# panic!("macros feature disabled");
# #[cfg(feature = "macros")] {
# use alloc_counter::{allow_alloc, no_alloc, AllocCounterSystem};
# #[global_allocator]
# static A: AllocCounterSystem = AllocCounterSystem;
#[no_alloc(forbid)]
fn foo(b: Box<i32>) {
allow_alloc(|| drop(b))
}
foo(Box::new(0));
# }
License: MIT OR Apache-2.0
Dependencies
~250KB