Skip to content

Commit

Permalink
v4.4.2 - doc improvements, warning fixes, deprecations
Browse files Browse the repository at this point in the history
  • Loading branch information
SFBdragon committed Oct 27, 2024
1 parent c180e65 commit 89b036f
Show file tree
Hide file tree
Showing 19 changed files with 139 additions and 73 deletions.
1 change: 0 additions & 1 deletion LICENSE.md

This file was deleted.

21 changes: 21 additions & 0 deletions LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright © 2023 Shaun Beautement

Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the “Software”),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
1 change: 0 additions & 1 deletion README_WASM.md

This file was deleted.

6 changes: 3 additions & 3 deletions benchmarks/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ talc = { path = "../talc" }
linked_list_allocator = { version = "0.10", features = ["use_spin_nightly", "const_mut_refs", "alloc_ref"] }
good_memory_allocator = { version = "0.1", features = ["spin", "allocator"] }
buddy-alloc = "0.5"
dlmalloc = { version = "0.2.4", default-features = false, features = ["global"] }
frusa = "0.1.2"
rlsf = "0.2.1"
dlmalloc = { version = "0.2", default-features = false, features = ["global"] }
frusa = "0.1"
rlsf = "0.2"
16 changes: 8 additions & 8 deletions benchmarks/microbench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use talc::{ErrOnOom, Talc};

use std::alloc::{GlobalAlloc, Layout};
use std::fs::File;
use std::ptr::NonNull;
use std::ptr::{addr_of_mut, NonNull};
use std::time::Instant;

const BENCH_DURATION: f64 = 1.0;
Expand All @@ -50,8 +50,8 @@ unsafe impl dlmalloc::Allocator for DlmallocArena {

if has_data {
let align = std::mem::align_of::<usize>();
let heap_align_offset = unsafe { HEAP_MEMORY.as_mut_ptr() }.align_offset(align);
unsafe { (HEAP_MEMORY.as_mut_ptr().add(heap_align_offset), (HEAP_SIZE - heap_align_offset) / align * align, 1) }
let heap_align_offset = addr_of_mut!(HEAP_MEMORY).align_offset(align);
unsafe { (addr_of_mut!(HEAP_MEMORY).cast::<u8>().add(heap_align_offset), (HEAP_SIZE - heap_align_offset) / align * align, 1) }
} else {
(core::ptr::null_mut(), 0, 0)
}
Expand Down Expand Up @@ -131,7 +131,7 @@ fn main() {
// warm up the memory caches, avoid demand paging issues, etc.
for i in 0..HEAP_SIZE {
unsafe {
HEAP_MEMORY.as_mut_ptr().add(i).write(0xAE);
addr_of_mut!(HEAP_MEMORY).cast::<u8>().add(i).write(0xAE);
}
}

Expand All @@ -143,15 +143,15 @@ fn main() {
let mut galloc_allocator =
good_memory_allocator::SpinLockedAllocator::<DEFAULT_SMALLBINS_AMOUNT>::empty();
unsafe {
galloc_allocator.init(HEAP_MEMORY.as_ptr() as usize, HEAP_SIZE);
galloc_allocator.init(addr_of_mut!(HEAP_MEMORY) as usize, HEAP_SIZE);
}

benchmark_allocator(&mut galloc_allocator, "Galloc", &mut csvs);

let buddy_alloc = unsafe {
buddy_alloc::NonThreadsafeAlloc::new(
FastAllocParam::new(HEAP_MEMORY.as_ptr(), HEAP_SIZE / 8),
BuddyAllocParam::new(HEAP_MEMORY.as_ptr().add(HEAP_SIZE / 8), HEAP_SIZE / 8 * 7, 64),
FastAllocParam::new(addr_of_mut!(HEAP_MEMORY).cast(), HEAP_SIZE / 8),
BuddyAllocParam::new(addr_of_mut!(HEAP_MEMORY).cast::<u8>().add(HEAP_SIZE / 8), HEAP_SIZE / 8 * 7, 64),
)
};
benchmark_allocator(&buddy_alloc, "Buddy Allocator", &mut csvs);
Expand All @@ -162,7 +162,7 @@ fn main() {
benchmark_allocator(&dlmalloc, "Dlmalloc", &mut csvs);

let talc = Talc::new(ErrOnOom).lock::<talc::locking::AssumeUnlockable>();
unsafe { talc.lock().claim(HEAP_MEMORY.as_mut().into()) }.unwrap();
unsafe { talc.lock().claim(addr_of_mut!(HEAP_MEMORY).into()) }.unwrap();

benchmark_allocator(&talc, "Talc", &mut csvs);

Expand Down
27 changes: 11 additions & 16 deletions benchmarks/random_actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// Modified by Shaun Beautement

#![feature(iter_intersperse)]
#![feature(const_mut_refs)]

use std::{
alloc::{GlobalAlloc, Layout},
ptr::NonNull,
sync::{Arc, Barrier},
time::{Duration, Instant},
fmt::Write
alloc::{GlobalAlloc, Layout}, fmt::Write, ptr::{addr_of_mut, NonNull}, sync::{Arc, Barrier}, time::{Duration, Instant}
};

use buddy_alloc::{BuddyAllocParam, FastAllocParam, NonThreadsafeAlloc};

const THREAD_COUNT: usize = 4;
const THREAD_COUNT: usize = 12;

const RA_TRIALS_AMOUNT: usize = 7;
const RA_TIME: Duration = Duration::from_millis(200);
Expand Down Expand Up @@ -275,14 +270,14 @@ impl<'a> Drop for AllocationWrapper<'a> {
unsafe fn init_talc() -> Box<dyn GlobalAlloc + Sync> {
unsafe {
let talck: _ = talc::Talc::new(talc::ErrOnOom).lock::<spin::Mutex<()>>();
talck.lock().claim(HEAP.as_mut_slice().into()).unwrap();
talck.lock().claim(addr_of_mut!(HEAP).into()).unwrap();
Box::new(talck)
}
}

unsafe fn init_linked_list_allocator() -> Box<dyn GlobalAlloc + Sync> {
let lla = linked_list_allocator::LockedHeap::new(HEAP.as_mut_ptr(), HEAP_SIZE);
lla.lock().init(HEAP.as_mut_ptr().cast(), HEAP_SIZE);
let lla = linked_list_allocator::LockedHeap::new(addr_of_mut!(HEAP).cast(), HEAP_SIZE);
lla.lock().init(addr_of_mut!(HEAP).cast(), HEAP_SIZE);
Box::new(lla)
}

Expand All @@ -299,7 +294,7 @@ unsafe fn init_galloc() -> Box<dyn GlobalAlloc + Sync> {
let galloc = good_memory_allocator::SpinLockedAllocator
::<{good_memory_allocator::DEFAULT_SMALLBINS_AMOUNT}, {good_memory_allocator::DEFAULT_ALIGNMENT_SUB_BINS_AMOUNT}>
::empty();
galloc.init(HEAP.as_ptr() as usize, HEAP_SIZE);
galloc.init(addr_of_mut!(HEAP) as usize, HEAP_SIZE);
Box::new(galloc)
}

Expand All @@ -311,10 +306,10 @@ unsafe fn init_rlsf() -> Box<dyn GlobalAlloc + Sync> {

unsafe fn init_buddy_alloc() -> Box<dyn GlobalAlloc + Sync> {
let ba = BuddyAllocWrapper(spin::Mutex::new(NonThreadsafeAlloc::new(
FastAllocParam::new(HEAP.as_ptr().cast(), HEAP.len() / 8),
FastAllocParam::new(addr_of_mut!(HEAP).cast(), HEAP_SIZE / 8),
BuddyAllocParam::new(
HEAP.as_ptr().cast::<u8>().add(HEAP.len() / 8),
HEAP.len() / 8 * 7,
addr_of_mut!(HEAP).cast::<u8>().add(HEAP_SIZE / 8),
HEAP_SIZE / 8 * 7,
64,
),
)));
Expand Down Expand Up @@ -378,8 +373,8 @@ unsafe impl dlmalloc::Allocator for DlmallocArena {
} else {
*lock = true;
let align = std::mem::align_of::<usize>();
let heap_align_offset = unsafe { HEAP.as_mut_ptr() }.align_offset(align);
(unsafe { HEAP.as_mut_ptr().add(heap_align_offset) }, (HEAP_SIZE - heap_align_offset) / align * align, 1)
let heap_align_offset = addr_of_mut!(HEAP).align_offset(align);
(unsafe { addr_of_mut!(HEAP).cast::<u8>().add(heap_align_offset) }, (HEAP_SIZE - heap_align_offset) / align * align, 1)
}
}

Expand Down
4 changes: 0 additions & 4 deletions check.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,6 @@ rustup run nightly cargo check -p benchmarks --bin random_actions

# check wasm size benches
./wasm-size.sh check
# check wasm size MSRV
rustup run 1.68 cargo check -p wasm-size --target wasm32-unknown-unknown

# check wasm perf benches
./wasm-perf.sh check
# check wasm perf MSRV
rustup run 1.73 wasm-pack --log-level warn build wasm-perf --dev --target web
6 changes: 6 additions & 0 deletions stable_examples/examples/stable_allocator_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ use allocator_api2::vec::Vec;

// Run with:
// `cargo +stable run -p stable_examples --example stable_allocator_api`
// `cargo miri run -p stable_examples --example stable_allocator_api`

// TODO: Change talc's configuration to be stable-by-default, which will
// avoid `rust-analyzer` complaining here about `Talck` not implementing
// `allocator_api2::alloc::Allocator` if `rust-analyzer` is using a nightly
// toolchain.

fn main() {
// Establish some memory for the allocator.
Expand Down
35 changes: 24 additions & 11 deletions stable_examples/examples/std_global_allocator.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,33 @@
use std::ptr::addr_of;

use talc::*;

// note:
// - Miri thinks this violates stacked borrows upon program termination.
// - This only occurs with `#[global_allocator]`.
// - Consider using the allocator API if you can't have that (see: `examples/stable_allocator_api.rs`)
// - `spin::Mutex<()>`
// The `spin` crate provides a mutex that is a sensible choice to use.
// - `ClaimOnOom`
// An OOM handler with support for claiming memory on-demand is required, as allocations may
// occur prior to the execution of `main()`.
// Run with:
// `cargo +stable run -p stable_examples --example std_global_allocator`
// `cargo miri run -p stable_examples --example std_global_allocator`

// Notes:
//
// ## Using `spin::Mutex<()>`
// The `spin` crate provides a simple mutex we can use on most platforms.
// We'll use it for the sake of example.
//
// ## Using `ClaimOnOom`
// An OOM handler with support for claiming memory on-demand is required, as allocations may
// occur prior to the execution of `main`.
//
// ## Arena pointer conversion from `*const` to `*mut`
// Without `const_mut_refs` being stable just yet, we need to get a mutable pointer
// indirectly. It's not clear whether this is acceptable (see: https://github.com/SFBdragon/talc/issues/32)
// but MIRI is fine with it and Rust's aliasing/provenance rules don't stipulate yet.
// Once Rust 1.83 lands with `const_mut_refs`, this example will be changed
// to just use `&raw mut`.

static mut START_ARENA: [u8; 10000] = [0; 10000];
static mut ARENA: [u8; 10000] = [0; 10000];

#[global_allocator]
static ALLOCATOR: Talck<spin::Mutex<()>, ClaimOnOom> = Talc::new(unsafe {
ClaimOnOom::new(Span::from_const_array(core::ptr::addr_of!(START_ARENA)))
ClaimOnOom::new(Span::from_array(addr_of!(ARENA) as *mut [u8; 10000]))
}).lock();

fn main() {
Expand Down
4 changes: 2 additions & 2 deletions talc/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
[package]
name = "talc"
version = "4.4.1"
version = "4.4.2"
rust-version = "1.67.1"
edition = "2021"
readme = "README.md"
authors = ["Shaun Beautement"]
authors = ["Shaun Beautement <sf.beautement@protonmail.com>"]
description = "A fast and flexible allocator for no_std and WebAssembly"
repository = "https://github.com/SFBdragon/talc"
keywords = ["allocator", "no_std", "memory", "heap", "wasm"]
Expand Down
20 changes: 15 additions & 5 deletions talc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
- Supports creating and resizing arbitrarily many heaps
- Optional allocation statistics
- Partial validation with debug assertions enabled
- Conforms to MIRI's stacked borrows checker
- Verified with MIRI

#### Why not Talc?
- Doesn't integrate with operating systems' dynamic memory facilities out-of-the-box yet
Expand All @@ -24,7 +24,7 @@

## Table of Contents

Targeting WebAssembly? You can find WASM-specific usage and benchmarks [here](https://github.com/SFBdragon/talc/README_WASM.md).
Targeting WebAssembly? You can find WASM-specific usage and benchmarks [here](https://github.com/SFBdragon/talc/blob/master/talc/README_WASM.md).

- [Setup](#setup)
- [Benchmarks](#benchmarks)
Expand Down Expand Up @@ -98,15 +98,15 @@ The number of successful allocations, deallocations, and reallocations within th

#### 1 Thread

![Random Actions Benchmark Results](https://github.com/SFBdragon/talc/benchmark_graphs/random_actions.png)
![Random Actions Benchmark Results](https://github.com/SFBdragon/talc/blob/master/talc/benchmark_graphs/random_actions.png?raw=true)

#### 4 Threads

![Random Actions Multi Benchmark Results](https://github.com/SFBdragon/talc/benchmark_graphs/random_actions_multi.png)
![Random Actions Multi Benchmark Results](https://github.com/SFBdragon/talc/blob/master/talc/benchmark_graphs/random_actions_multi.png?raw=true)

## Allocations & Deallocations Microbenchmark

![Microbenchmark Results](https://github.com/SFBdragon/talc/benchmark_graphs/microbench.png)
![Microbenchmark Results](https://github.com/SFBdragon/talc/blob/master/talc/benchmark_graphs/microbench.png?raw=true)

Label indicates the maximum within 50 standard deviations from the median. Max allocation size is 0x10000.

Expand Down Expand Up @@ -216,6 +216,16 @@ Update: All of this is currently in the works. No guarantees on when it will be

## Changelog


#### v4.4.2

- [polarathene](https://github.com/polarathene): Replace README relative links with fully-qualified links.
- [polarathene](https://github.com/polarathene): Improve docs for `stable_examples/examples/std_global_allocator.rs`.

- Improved docs for `stable_examples/examples/stable_allocator_api.rs` and `stable_examples/examples/std_global_allocator.rs`.
- Deprecated the `Span::from*` function for converting from shared references and const pointers, as they make committing UB easy. These will be removed in v5.
- Fixed up a bunch of warnings all over the project.

#### v4.4.1

- Added utility function `except` to `Span`, which takes the set difference, potentially splitting the `Span`. Thanks [bjorn3](https://github.com/bjorn3) for the suggestion!
Expand Down
Binary file modified talc/benchmark_graphs/random_actions.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified talc/benchmark_graphs/random_actions_multi.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 1 addition & 3 deletions talc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@
//! Calling `Talc::lock()` on it will yield a `Talck` which implements
//! [`GlobalAlloc`] and [`Allocator`] (if the appropriate feature flags are set).

#![cfg_attr(not(any(test, fuzzing)), no_std)]
#![cfg_attr(not(any(test, feature = "fuzzing")), no_std)]
#![cfg_attr(feature = "allocator", feature(allocator_api))]
#![cfg_attr(feature = "nightly_api", feature(slice_ptr_len))]
#![cfg_attr(feature = "nightly_api", feature(const_slice_ptr_len))]

mod oom_handler;
mod ptr_utils;
Expand Down
24 changes: 24 additions & 0 deletions talc/src/span.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ impl<T> From<Range<*mut T>> for Span {
}
}

// NOTE: This should be removed in a future release as it encouraged UB.
// Once `const_mut_refs` is stabilized in Rust, this will no longer be useful anyway.
// See: https://github.com/SFBdragon/talc/issues/33
impl<T> From<Range<*const T>> for Span {
fn from(value: Range<*const T>) -> Self {
Self { base: value.start.cast_mut().cast(), acme: value.end.cast_mut().cast() }
Expand All @@ -58,6 +61,9 @@ impl<T> From<&mut [T]> for Span {
}
}

// NOTE: This should be removed in a future release as it encouraged UB.
// Once `const_mut_refs` is stabilized in Rust, this will no longer be useful anyway.
// See: https://github.com/SFBdragon/talc/issues/33
impl<T> From<&[T]> for Span {
fn from(value: &[T]) -> Self {
Self::from(value.as_ptr_range())
Expand All @@ -70,6 +76,9 @@ impl<T, const N: usize> From<&mut [T; N]> for Span {
}
}

// NOTE: This should be removed in a future release as it encouraged UB.
// Once `const_mut_refs` is stabilized in Rust, this will no longer be useful anyway.
// See: https://github.com/SFBdragon/talc/issues/33
impl<T, const N: usize> From<&[T; N]> for Span {
fn from(value: &[T; N]) -> Self {
Self::from(value as *const [T; N])
Expand All @@ -83,9 +92,13 @@ impl<T> From<*mut [T]> for Span {
}
}

// NOTE: This should be removed in a future release as it encouraged UB.
// Once `const_mut_refs` is stabilized in Rust, this will no longer be useful anyway.
// See: https://github.com/SFBdragon/talc/issues/33
#[cfg(feature = "nightly_api")]
impl<T> From<*const [T]> for Span {
fn from(value: *const [T]) -> Self {
#[expect(deprecated)] // This impl is 'deprecated' too.
Self::from_const_slice(value)
}
}
Expand All @@ -96,6 +109,9 @@ impl<T, const N: usize> From<*mut [T; N]> for Span {
}
}

// NOTE: This should be removed in a future release as it encouraged UB.
// Once `const_mut_refs` is stabilized in Rust, this will no longer be useful anyway.
// See: https://github.com/SFBdragon/talc/issues/33
impl<T, const N: usize> From<*const [T; N]> for Span {
fn from(value: *const [T; N]) -> Self {
Self::from_array(value.cast_mut())
Expand Down Expand Up @@ -165,6 +181,10 @@ impl Span {
}
}

// NOTE: This should be removed in a future release as it encouraged UB.
// Once `const_mut_refs` is stabilized in Rust, this will no longer be useful anyway.
// See: https://github.com/SFBdragon/talc/issues/33
#[deprecated = "Conversion from const references encourages UB. This will be removed in a future release."]
#[cfg(feature = "nightly_api")]
#[inline]
pub const fn from_const_slice<T>(slice: *const [T]) -> Self {
Expand All @@ -186,6 +206,10 @@ impl Span {
}
}

// NOTE: This should be removed in a future release as it encouraged UB.
// Once `const_mut_refs` is stabilized in Rust, this will no longer be useful anyway.
// See: https://github.com/SFBdragon/talc/issues/33
#[deprecated = "Conversion from const references encourages UB. This will be removed in a future release."]
#[inline]
pub const fn from_const_array<T, const N: usize>(array: *const [T; N]) -> Self {
Self {
Expand Down
Loading

0 comments on commit 89b036f

Please sign in to comment.