Skip to content

hex-ley/SwiftAllocators

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 

Repository files navigation

SwiftAllocators

Foundation-less and cross-platform implementations of specialized memory allocators, designed for maximum performance and control.

Requirements

  • Swift 6.0 or later

  • No Foundation required

Getting started

Add the package to your Package.swift dependencies:

.package(url: "https://github.com/hex-ley/SwiftAllocators.git", from: "0.1.0")

Then add "Allocators" to the targets that need it:

.target(
    name: "MyTarget",
    dependencies: [
        "...",
        "...",
        "Allocators"
    ]
)

Basic Usage

UnsafeMemoryArena

An arena / bump allocator implementation.

Useful for performance-critical systems, where many allocations share the same lifetime (e.g. per-frame data in games, temporary buffers when parsing, AST nodes and IR code in compilers, or request-scoped data in servers). Avoids fragmentation and reduces overhead compared to general-purpose allocators. Allocation will always succeed regardless of the requested size, given that the system allocator does not fail.

Allocations are served from a large backing memory block, which is allocated up front from the system allocator. Allocations are handed out sequentially by bumping an interal offset into the backing memory block, making it extremely fast. Instead of individual deallocations, all memory is reclaimed at once by destroying the arena, reducing the risk of a memory leak and the number of system calls.

import Allocators

var arena = UnsafeMemoryArena(blockSize: 4096)

let intPtr = arena.allocate(initializedTo: 42)
let rawPtr = arena.allocate(byteCount: 128, alignment: 8)
// pass around pointers, or compute something

arena.destroy()
// all pointers obtained above are now invalid

Performance is traded for security. Using an UnsafeMemoryArena requires strict lifetime discipline. You may not free individual allocations; instead you must manually destroy the arena after use. All pointers recieved from the arena become dangling after.

For convenience, the function scopedMemoryArena(withBlockSize:_:) is provided. It creates a new arena of the given size, runs the closure, and automatically destroys the arena after:

let result = scopedMemoryArena(withBlockSize: 4096) { arena in

    let intPtr = arena.allocate(initializedTo: 42)
    let rawPtr = arena.allocate(byteCount: 128, alignment: 8)

    return computeSomething(intPtr, rawPtr)
}
// arena destroyed

Types, which are not trivially destructible, must be destroyed manually. Note that allocating containers from the standard library (such as Array or String) is most likely a sign of misuse. These types manage their own storage outside the arena, with the difference that their destructors may not be run. In such cases, the arena provides no benefit.

 

⚠️

This API trades Swift’s usual memory safety for performance. Developer discipline is required, and following rules must be followed:

  1. The arena must be destroyed manually.
    Call destroy(), or use scopedMemoryArena(withBlockSize:_:) to have it called for you.

  2. Never use a pointer after the arena is destroyed.
    All pointers vended by an arena become dangling the moment it is destroyed.

  3. Never call deallocate() on pointers returned by the arena.
    The system allocator does not know about individual allocations made by the arena. Trying to deallocate them individually is UB.

  4. Non-trivial types must be destroyed manually.
    On arena destruction, only the backing memory is deallocated. The destructor of types, which own external resources, will not be run automatically.

License

This package is released under the MIT License. See LICENSE for details.

About

specialized memory allocators for Swift, designed for maximum performance and control

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors