ℹ️ Select 'Choose Exercise', or randomize 'Next Random Exercise' in selected language.

Choose Exercise:
Timer 00:00
WPM --
Score --
Acc --
Correct chars --

Zig Custom Allocator with Arena

Zig

Goal -- WPM

Ready
Exercise Algorithm Area
1const std = @import("std");
2
3const ArenaAllocator = struct {
4memory: []u8,
5current: usize,
6capacity: usize,
7
8pub fn init(capacity: usize) ArenaAllocator {
9var memory = std.heap.page_allocator.alloc(capacity) catch unreachable;
10return ArenaAllocator {
11.memory = memory,
12.current = 0,
13.capacity = capacity,
14};
15}
16
17pub fn deinit(self: *ArenaAllocator) void {
18std.heap.page_allocator.dealloc(self.memory);
19}
20
21pub fn alloc(self: *ArenaAllocator, size: usize, align: usize) ![]u8 {
22const aligned_size = std.mem.align(size, align);
23if (self.current + aligned_size > self.capacity) {
24return error.OutOfMemory;
25}
26
27const ptr = self.memory[self.current..self.current + aligned_size];
28self.current += aligned_size;
29return ptr;
30}
31
32pub fn dealloc(self: ArenaAllocator, _ptr: []u8, _size: usize) void {
33// Arena allocators typically do not deallocate individual items.
34// All memory is reclaimed when the arena is reset or deinitialized.
35_ = self;
36_ = _ptr;
37_ = _size;
38}
39
40pub fn reset(self: *ArenaAllocator) void {
41self.current = 0;
42}
43};
44
45fn createAndUseArena() !void {
46var arena = ArenaAllocator.init(1024);
47defer arena.deinit();
48
49const data1 = try arena.alloc(10, 8);
50std.debug.print("Allocated data1 at: {any}", .{@ptrToInt(data1)});
51
52const data2 = try arena.alloc(20, 4);
53std.debug.print("Allocated data2 at: {any}", .{@ptrToInt(data2)});
54
55// Attempt to allocate more than capacity
56_ = try arena.alloc(1000, 1);
57
58arena.reset();
59std.debug.print("Arena reset.", .{});
60
61const data3 = try arena.alloc(5, 2);
62std.debug.print("Allocated data3 after reset at: {any}", .{@ptrToInt(data3)});
63}
64
65pub fn main() !void {
66createAndUseArena() catch |err| {
67if (err == error.OutOfMemory) {
68std.debug.print("Failed to allocate memory: Out of Memory\n", .{});
69} else {
70std.debug.print("An unexpected error occurred: {anyerr}\n", .{err});
71}
72};
73}
Algorithm description viewbox

Zig Custom Allocator with Arena

Algorithm description:

This Zig code implements a simple arena allocator. An arena allocator is a memory management technique where memory is allocated from a large pre-allocated block (the arena). Unlike traditional allocators, individual allocations within an arena are typically not deallocated; instead, the entire arena is reset or deallocated at once. This is useful for scenarios where many small, short-lived allocations are made, such as during parsing or temporary data structure construction, as it can significantly reduce fragmentation and overhead.

Algorithm explanation:

The `ArenaAllocator` struct manages a contiguous block of memory. The `init` function allocates the memory block and initializes the `current` pointer to the beginning. The `alloc` function calculates the aligned size needed, checks for sufficient capacity, and returns a slice from the `memory` array, advancing the `current` pointer. Crucially, `dealloc` is a no-op, as individual deallocations are not supported. The `reset` function simply sets `current` back to 0, effectively making all previously allocated memory available again. The `createAndUseArena` function demonstrates allocation, including an out-of-memory scenario, and resetting the arena. Time complexity for `alloc` is O(1) as it's just pointer arithmetic and a capacity check. Space complexity is O(N) where N is the arena's capacity. Edge cases include attempting to allocate more memory than available and ensuring correct alignment.

Pseudocode:

ArenaAllocator:
  memory: byte array
  current_offset: integer
  capacity: integer

init(capacity):
  allocate memory block of capacity
  return ArenaAllocator with memory, current_offset=0, capacity

deinit():
  free memory block

alloc(size, align):
  calculate aligned_size = align_up(size, align)
  if current_offset + aligned_size > capacity:
    return OutOfMemory error
  allocate slice from memory at current_offset with aligned_size
  increment current_offset by aligned_size
  return slice

dealloc(ptr, size):
  do nothing (no-op)

reset():
  set current_offset to 0