{"id":13626709,"url":"https://github.com/fengb/zee_alloc","last_synced_at":"2026-02-24T19:43:30.579Z","repository":{"id":46450341,"uuid":"187853027","full_name":"fengb/zee_alloc","owner":"fengb","description":"tiny Zig allocator primarily targeting WebAssembly","archived":false,"fork":false,"pushed_at":"2021-06-05T13:18:07.000Z","size":604,"stargazers_count":87,"open_issues_count":6,"forks_count":7,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-03-16T10:24:51.629Z","etag":null,"topics":["memory-allocation","tiny","wasm","zig"],"latest_commit_sha":null,"homepage":"https://fengb.github.io/zee_alloc/#root","language":"Zig","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fengb.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-05-21T14:23:17.000Z","updated_at":"2025-03-10T19:05:16.000Z","dependencies_parsed_at":"2022-09-15T21:22:38.910Z","dependency_job_id":null,"html_url":"https://github.com/fengb/zee_alloc","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fengb%2Fzee_alloc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fengb%2Fzee_alloc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fengb%2Fzee_alloc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fengb%2Fzee_alloc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fengb","download_url":"https://codeload.github.com/fengb/zee_alloc/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244008875,"owners_count":20382926,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["memory-allocation","tiny","wasm","zig"],"created_at":"2024-08-01T21:02:27.311Z","updated_at":"2026-02-24T19:43:25.557Z","avatar_url":"https://github.com/fengb.png","language":"Zig","readme":"# zee_alloc — *zig wee allocator*\n\nA tiny general purpose allocator targeting WebAssembly.\n\nThis allocator has not been well tested. Use at your own peril.\n\n### Getting Started\n\nIn zig:\n\n```zig\nconst zee_alloc = @import(\"zee_alloc\");\n\npub fn foo() void {\n    var mem = zee_alloc.ZeeAllocDefaults.wasm_allocator.alloc(u8, 1000);\n    defer zee_alloc.ZeeAllocDefaults.wasm_allocator.free(mem);\n}\n```\n\nExporting into wasm:\n\n```zig\nconst zee_alloc = @import(\"zee_alloc\");\n\ncomptime {\n    (zee_alloc.ExportC{\n        .allocator = zee_alloc.ZeeAllocDefaults.wasm_allocator,\n        .malloc = true,\n        .free = true,\n        .realloc = false,\n        .calloc = false,\n    }).run();\n  }\n```\n\n### Goals\n\n_(inspired by Rust's [wee_alloc](https://github.com/rustwasm/wee_alloc))_\n\n1. Tiny compiled output\n2. Tiny compiled output x2\n3. Malloc/free compatibility\n4. Avoid long-term fragmentation\n5. Reasonably fast alloc and free\n6. Code simplicity — probably goes in hand with tiny output\n\n**Non-goals**\n\n- Debugging — this library probably will never do a good job identifying errors.\n  Zig has a great [debug allocator](https://github.com/andrewrk/zig-general-purpose-allocator)\n  in the works, and zig programs should be able to easily swap allocators.\n- Compact memory — fixed allocation frames are used for speed and simplicity.\n  Memory usage will never be optimum unless the underlying algorithm completely changes\n- Thread performance — wasm is single-threaded\n\n### Benchmarks\n\n```\nBenchmark                                   Mean(ns)\n----------------------------------------------------\nDirectAllocator.0                              50842\nDirectAllocator.1                              98343\nDirectAllocator.2                             203980\nDirectAllocator.3                              49908\nDirectAllocator.4                             103635\nDirectAllocator.5                             195941\nDirectAllocator.6                              47367\nDirectAllocator.7                             101733\nDirectAllocator.8                             202697\nArena_DirectAllocator.0                        11837\nArena_DirectAllocator.1                        19591\nArena_DirectAllocator.2                        30689\nArena_DirectAllocator.3                        30916\nArena_DirectAllocator.4                        52425\nArena_DirectAllocator.5                        75673\nArena_DirectAllocator.6                        44874\nArena_DirectAllocator.7                        67557\nArena_DirectAllocator.8                        96276\nZeeAlloc_DirectAllocator.0                     15892\nZeeAlloc_DirectAllocator.1                     24435\nZeeAlloc_DirectAllocator.2                     49564\nZeeAlloc_DirectAllocator.3                     26656\nZeeAlloc_DirectAllocator.4                     52462\nZeeAlloc_DirectAllocator.5                     93854\nZeeAlloc_DirectAllocator.6                     51493\nZeeAlloc_DirectAllocator.7                     95223\nZeeAlloc_DirectAllocator.8                    250187\nFixedBufferAllocator.0                           177\nFixedBufferAllocator.1                           412\nFixedBufferAllocator.2                          1006\nFixedBufferAllocator.3                           296\nFixedBufferAllocator.4                           785\nFixedBufferAllocator.5                          1721\nFixedBufferAllocator.6                           848\nFixedBufferAllocator.7                          1546\nFixedBufferAllocator.8                          3331\nArena_FixedBufferAllocator.0                     299\nArena_FixedBufferAllocator.1                     573\nArena_FixedBufferAllocator.2                    1624\nArena_FixedBufferAllocator.3                    1115\nArena_FixedBufferAllocator.4                    1868\nArena_FixedBufferAllocator.5                    4422\nArena_FixedBufferAllocator.6                    1706\nArena_FixedBufferAllocator.7                    3389\nArena_FixedBufferAllocator.8                    8430\nZeeAlloc_FixedBufferAllocator.0                  232\nZeeAlloc_FixedBufferAllocator.1                  577\nZeeAlloc_FixedBufferAllocator.2                 1165\nZeeAlloc_FixedBufferAllocator.3                  443\nZeeAlloc_FixedBufferAllocator.4                  907\nZeeAlloc_FixedBufferAllocator.5                 1848\nZeeAlloc_FixedBufferAllocator.6                  907\nZeeAlloc_FixedBufferAllocator.7                 1721\nZeeAlloc_FixedBufferAllocator.8                 3836\n```\n\n### Architecture — [Buddy memory allocation](https://en.wikipedia.org/wiki/Buddy_memory_allocation)\n\n_Caveat: I knew **nothing** about memory allocation when starting this project.\nAny semblence of competence is merely a coincidence._\n\n```\nidx frame_size\n 0  \u003e65536  jumbo\n 1   65536  wasm page size\n 2   32768\n 3   16384\n 4    8192\n 5    4096\n 6    2048\n 7    1024\n 8     512\n 9     256\n10     128\n11      64\n12      32\n13      16  smallest frame\n```\n\nSize order is reversed because 0 and 1 are special.  I believe counting down had\nslightly better semantics than counting up but I haven't actually tested it.\n\nWasm only allows for allocating entire pages (64K) at a time. Current architecture is\nheavily influenced by this behavior. In a real OS, the page size is much smaller at 4K.\nEverything should work as expected even if it does not run as efficient as possible.\n\nEach allocation frame consists of 2 usizes of metadata: the frame size and a pointer to\nthe next free node. This enables some rudimentary debugging as well as a simple lookup\nwhen we only have the allocated data-block (especially important for C compatibility).\n\nFor allocations \u003c=64K in size, we find the smallest usable free frame.  If it's\nbigger than necessary, we grab the smallest power of 2 we need and resize the rest\nto toss back as free nodes. This is O(log k) which is O(1).\n\nFor allocations \u003e64K, we iterate through list 0 to find a matching size, O(n).\nFree jumbo frames are never divided into smaller allocations.\n\nZeeAlloc only supports pointer alignment at 2x usize — 8 bytes in wasm. There\nare a few ideas to expand this to up-to half page_size but nothing concrete yet.\n","funding_links":[],"categories":["Zig","Libraries","Web","Language Essentials"],"sub_categories":["Memory Allocator and Management"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffengb%2Fzee_alloc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffengb%2Fzee_alloc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffengb%2Fzee_alloc/lists"}