{"id":26600806,"url":"https://github.com/nim-works/loony","last_synced_at":"2025-04-09T16:23:59.229Z","repository":{"id":44930743,"uuid":"406617799","full_name":"nim-works/loony","owner":"nim-works","description":"A high throughput MPMC lock-free queue based on a paper by Giersch, Nolte et al implemented in pure Nim.","archived":false,"fork":false,"pushed_at":"2024-09-08T03:22:17.000Z","size":872,"stargazers_count":67,"open_issues_count":3,"forks_count":4,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-03-23T18:47:55.538Z","etag":null,"topics":["concurrency","fifo","lock-free","mpmc","nim","nim-lang","nimskull","parallelism","queue"],"latest_commit_sha":null,"homepage":"https://nim-works.github.io/loony/","language":"Nim","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/nim-works.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-09-15T04:51:10.000Z","updated_at":"2025-01-24T23:46:30.000Z","dependencies_parsed_at":"2023-01-11T15:38:27.913Z","dependency_job_id":"1c43f11d-dc4c-4472-b23e-aa9352e70dbf","html_url":"https://github.com/nim-works/loony","commit_stats":null,"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nim-works%2Floony","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nim-works%2Floony/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nim-works%2Floony/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nim-works%2Floony/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nim-works","download_url":"https://codeload.github.com/nim-works/loony/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248066002,"owners_count":21042014,"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":["concurrency","fifo","lock-free","mpmc","nim","nim-lang","nimskull","parallelism","queue"],"created_at":"2025-03-23T18:35:30.610Z","updated_at":"2025-04-09T16:23:59.203Z","avatar_url":"https://github.com/nim-works.png","language":"Nim","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n\u003cdiv align=\"center\"\u003e\n\t\u003cbr\u003e\n\t\u003ca href=\"https://github.com/nim-works/loony\"\u003e\n\t\t\u003cimg src=\"papers/header.svg\" width=\"800\" height=\"200\" alt=\"Loony\"\u003e\n\t\u003c/a\u003e\n\t\u003cbr\u003e\n\n[![Test Matrix](https://github.com/disruptek/cps/workflows/CI/badge.svg)](https://github.com/shayanhabibi/loony/actions?query=workflow%3ACI)\n[![GitHub release (latest by date)](https://img.shields.io/github/v/release/shayanhabibi/loony?style=flat)](https://github.com/shayanhabibi/loony/releases/latest)\n![Minimum supported Nim version](https://img.shields.io/badge/nim-1.5.1%2B-informational?style=flat\u0026logo=nim)\n[![License](https://img.shields.io/github/license/shayanhabibi/loony?style=flat)](#license)\n\u003c/div\u003e\n\n\u003c!-- # Loony --\u003e\n\u003e*\"Don't let me block you\" - Araq*\n\u003e\n\u003e*\"We didn't have a good story about migrating continuations between threads.\" - Disruptek*\n\nHave you ever asked yourself what would a lock-free MPMC queue look like in nim?\n\nWhat about a lock-free MPMC queue designed on an algorithm built for speed and memory safety?\n\nWhat about that algorithm implemented by some ***loonatics***?\n\nEnter **Loony**\n\n\u003e*\"C'mon man... 24,000 threads and 500,000,000 continuations... which are written in \"normal\" nim.\" - Disruptek*\n\u003e\n\u003e*\"OK, time to get my monies worth from all my cores\" - saem*\n\u003e\n\u003e*\"My eyes are bleeding\" - cabboose*\n\n## About\n\n\u003e A massive thank you to the author Oliver Giersch who proposed this algorithm and for being so kind as to have a look at our implementation and review it! We wish nothing but the best for the soon to be Dr Giersch.\n\n\nLoony is a 100% Nim-lang implementation of the algorithm depicted by Giersch \u0026 Nolte in [\"Fast\nand Portable Concurrent FIFO Queues With Deterministic Memory Reclamation\"](papers/GierschEtAl.pdf).\n\nThe algorithm was chosen to help progress the concurrency story of [CPS](https://github.com/nim-works/cps) for which this was bespokingly made.\n\nAfter adapting the algorithm to nim CPS, disruptek adapted the queue for **any ref object** and was instrumental in ironing out the bugs and improving the performance of Loony.\n\n## What can it do\n\n\u003e While the following is possible; this is only by increasing the alignment our 'node' pointers to 16 which would invariably effect performance.\n\u003e- Lock-free consumption by up to **32,255** threads\n\u003e- Lock-free production by up to **64,610** threads\n\u003e\n\u003e You can use `-d:loonyNodeAlignment=16` or whatever alignment you wish to adjust the contention capacity.\n\nWith the 11 bit aligned implementation we have:\n- Lock-free consumption up to **512** threads\n- Lock-free production up to **1,025** threads\n- Memory-leak free under **ARC**\n- Can pass ANY ref object between threads; however:\n  - Is perfectly designed for passing Continuations between threads\n- **0 memory copies**\n\n## Issues\n\n**Loony queue only works on ARC**.\n\nORC is not supported (See [Issue #4](https://github.com/shayanhabibi/loony/issues/4))\n\nSpawn (Nims `threadpool` module) is not supported. *It won't ever be; don't use spawn unless you are a masochist in general.*\n## Installation\n\nDownload with `nimble install loony` (CPS dependency for tests) or directly from the source.\n\n### How to use\n\nSimple.\n\nFirst, ensure you compile with arc and threads (`--gc:arc --threads:on`)\n\nThen:\n```nim\nimport pkg/loony\n\ntype TestRef = ref object\n\nlet loonyQueue = newLoonyQueue[TestRef]()\n# Loony takes reference pointers and sends them safely!\n\nvar aro = new TestRef\n\nloonyQueue.push aro\n# Enqueue objects onto the queue\n# unsafePush is available, see MemorySafety \u0026 Cache Coherance below!\n\nvar el = loonyQueue.pop\n# Dequeue objects from the queue\n# unsafePop is available, see MemorySafety \u0026 Cache Coherance below!\n```\n\nThere is now a preliminary sublibrary which provides state managers called `Ward`'s.\nThese can be imported with `import loony/ward`. The documentation is found below,\ntests and further documentation are to follow when time allows.\n\n## Documentation\n\n[The full API documentation is kept up-to-date on GitHub.](https://nim-works.github.io/loony/loony.html)\n\n[~~The API documentation for the Ward submodule is found here.~~](https://nim-works.github.io/loony/loony/ward.html) ~~*Wards are untested and are unlikely to remain in the library*~~\n\n#### Memory Safety \u0026 Cache Coherence\n\nLoony's standard `push` and `pop` operations offer cache coherency by using\nprimitives such as `atomic_thread_fence` to ensure a CPU's store buffer is\ncommitted on the push operation and read on the pop operation; this is a\nhigher-cost primitive. You can use `unsafePush` and `unsafePop` to manipulate\na `LoonyQueue` without regard to cache coherency for ultimate performance.\n\nThe LoonyQueue itself is padded across cachelines, and by default, the slots\nare read and written to in a cyclic fashion over cachelines to reduce false\nsharing.\n\n```\nVisual representation of rotating index\n\n| 64 bytes | 64 bytes | 64 bytes |...\n| 0------- | 1------- | 2------- |...\n| -63------| -64------| -65------|...\n|--127-----|--128-----|--129-----|...\n```\n\n### Debugging\n\nPass `--d:loonyDebug` in compilation or with a config nimscript to use debug\nprocedures and templates.\n\n\u003e Warning :warning: this switch causes node allocations and deallocations to\n\u003e write on an atomic counter which does marginally effect performance!\n\n`echoDebugNodeCounter() # Echos the current number of nodes in the queue`\n\n```nim\ndebugNodeCounter:\n  # Put things onto the queue an off the queue here! At the\n  # end of the template, if the number of nodes you started\n  # with does not equal the number of nodes you finished\n  # the block with, it will print information that is useful\n  # to finding the source of the leak! This template will not\n  # do anything if loonyDebug is off.\n  discard\n```\n\n### Compiler Flags\n\nWe recommend against changing these values unless you know what you are doing. The suggested max alignment is 16 to achieve drastically higher contention capacities. Compilation will fail if your alignment does not fit the slot count index.\n\n`-d:loonyNodeAlignment=11` - Adjust node alignment to increase/decrease contention capacity\n\n`-d:loonySlotCount=1024` - Adjust the number of slots in each node\n\n`-d:loonyDebug=false` - Toggle debug counters and templates, see\n[debugging](#debugging). False by default.\n\n`-d:loonyRotate=true` - Toggle the index for the slots of\nloony queue to be read over cacheline bounds in a cyclic\nmanner. True by default.\n\n\u003e While loonyRotate is enabled, the slot count must be a\n\u003e power of 2. Error messages will indicate whether this\n\u003e is a cause of compilation failure.\n\n## What are Continuations?\n\nIf you've somehow missed the next big thing for nim; see [CPS](https://github.com/nim-works/cps)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnim-works%2Floony","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnim-works%2Floony","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnim-works%2Floony/lists"}