{"id":13627491,"url":"https://github.com/kleinron/lite-fifo","last_synced_at":"2025-04-16T23:33:10.135Z","repository":{"id":40456553,"uuid":"411016896","full_name":"kleinron/lite-fifo","owner":"kleinron","description":"Lightweight and efficient implementations of FIFO/Queue, written in pure javascript","archived":false,"fork":false,"pushed_at":"2024-08-23T20:14:38.000Z","size":140,"stargazers_count":27,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-13T21:17:34.383Z","etag":null,"topics":["data-structures","fifo","fifo-queue","lightweight","queue","zero-dependency"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/kleinron.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-27T19:28:33.000Z","updated_at":"2025-03-31T05:44:41.000Z","dependencies_parsed_at":"2024-08-20T15:18:16.485Z","dependency_job_id":null,"html_url":"https://github.com/kleinron/lite-fifo","commit_stats":{"total_commits":62,"total_committers":3,"mean_commits":"20.666666666666668","dds":"0.30645161290322576","last_synced_commit":"7d48c41a33a0d6cb4fc56470c46b4ec9519ba2c6"},"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kleinron%2Flite-fifo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kleinron%2Flite-fifo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kleinron%2Flite-fifo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kleinron%2Flite-fifo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kleinron","download_url":"https://codeload.github.com/kleinron/lite-fifo/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249288027,"owners_count":21244717,"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":["data-structures","fifo","fifo-queue","lightweight","queue","zero-dependency"],"created_at":"2024-08-01T22:00:34.739Z","updated_at":"2025-04-16T23:33:09.885Z","avatar_url":"https://github.com/kleinron.png","language":"JavaScript","funding_links":[],"categories":["Projects by main language"],"sub_categories":["javascript"],"readme":"[![NPM version](https://img.shields.io/npm/v/lite-fifo.svg?style=flat)](https://npmjs.org/package/lite-fifo)\n[![CI](https://github.com/kleinron/lite-fifo/actions/workflows/main.yaml/badge.svg)](https://github.com/kleinron/lite-fifo/actions/workflows/main.yaml)\n[![GitHub license](https://img.shields.io/github/license/kleinron/lite-fifo)](https://github.com/kleinron/lite-fifo/blob/main/LICENSE)\n\n# lite-fifo\n\nWhen you're short on RAM but still want a decent FIFO implementation...\n\n## Lightweight and efficient Queue implementations\nThis package aims to provide zero-dependency implementations of a queue, focusing on:\n* memory footprint (RAM)\n* throughput (ops/sec)  \n\nThe production code is dependency free. The only dependencies are for testing.\n\n## Benchmarks\nAfter running several scenarios and comparing to several known implementations, \nit's clear that this project's flagship `ChunkedQueue` has the lowest RAM usage, with a reasonable throughput (ops/sec). See [benchmarks.md](benchmarks.md) file for a deeper view and analysis. \n\n## Installation\n```bash\nnpm install lite-fifo\n```\n\n## Usage\n```javascript\nconst { ChunkedQueue } = require('lite-fifo');\n\nconst queue = new ChunkedQueue();\nqueue.enqueue(123);\nqueue.enqueue(45);\nqueue.enqueue(67);\n\nconsole.log(queue.toJSON());\n// =\u003e [ 123, 45, 67 ]\n\nconst temp = queue.dequeue(); // holds 123\nconsole.log(queue.toJSON());\n// =\u003e [ 45, 67 ]\n```\n\n# API\n## Classes\n* LinkedQueue\n* CyclicQueue (bounded)\n* DynamicCyclicQueue (unbounded)\n* ChunkedQueue\n* DynamicArrayQueue\n\nAll of these classes support the following methods\n## Methods\n### `enqueue (item)`  \nAdd an item to the queue.  \nBounded implementations might throw an exception if the capacity is exceeded.\n\n### `dequeue ()`\nReturn the first inserted (or the \"oldest\") item in the queue, and removes it from the queue.  \nZero sized queue would throw an exception.\n\n### `clear ()`\nClear the queue.\n\n### `size ()`\nReturn the current size of the queue.\n\n### `peekFirst ()`\nReturn the first inserted (or the \"oldest\") item in the queue, without removing it from the queue.  \nZero sized queue would throw an exception.\n\n### `peekLast ()`\nReturn the last inserted (or the \"newest\") item in the queue, without removing it from the queue.  \nZero sized queue would throw an exception.\n\n### `[Symbol.iterator] ()`\nIterate over the items in the queue without changing the queue.  \nIteration order is the insertion order: first inserted item would be returned first.  \nIn essence this supports JS iterations of the pattern `for (let x of queue) { ... }`.  \nExample:  \n```javascript\nconst queue = new ChunkedQueue();\nqueue.enqueue(123);\nqueue.enqueue(45);\nfor (let item of queue) {\n  console.log(item);\n}\n// ==\u003e output would be:\n// 123\n// 45\n// and the queue would remain unchanged\n```\n\n### `drainingIterator ()`\nIterate over the items in the queue.  \nEvery iterated item is removed from the queue.  \nIteration order is the insertion order: first inserted item would be returned first.  \nExample:\n```javascript\nconst queue = new ChunkedQueue();\nqueue.enqueue(123);\nqueue.enqueue(45);\nfor (let item of queue.drainingIterator()) {\n  console.log(item);\n}\nconsole.log(`size = ${queue.size()}`);\n// ==\u003e output would be:\n// 123\n// 45\n// size = 0\n```\n\n### `copyTo (arr, startIndex)`\n`startIndex` is optional, and defaults to 0 if not given.  \nCopy the items of the queue to the given array `arr`, starting from index `startIndex`.  \nFirst item in the array is first item inserted to the queue, and so forth.  \nNo return value.\n\n### `toArray ()`\nCreate an array with the same size as the queue, populate it with the items in the queue, keeping the iteration order, and return it.\n\n### `toJSON ()`\nReturn a JSON representation (as a string) of the queue.  \nThe queue is represented as an array: first item in the array is the first one inserted to the queue and so forth.\n\n## Common implementations and mistakes\n### Array + push + shift\nA very common implementation of a queue looks like this:\n```javascript\nclass DynamicArrayQueue { /* DON'T USE THIS CODE, IT DOESN'T SCALE */\n    constructor() {\n        this._arr = [];\n    }\n    enqueue(item) {\n        this._arr.push(item);\n    }\n    dequeue() {\n        return this._arr.shift();\n    }\n}\n```\nThe time complexity of the `dequeue` operation is O(n). At small scale - we wouldn't notice.  \nOn a high scale, say 300000 items, this implementation would have only 5 (five!) ops per second. Complexity matters..  \nAt the bottom line, this implementation is a mistake.\n\n### Linked List\nA linked list implementation for a queue behaves very well in terms of time complexity: O(1).  \nOn the memory side, the provided implementation, `LinkedQueue`, introduces an optimization: instead of relying on a doubly-linked-list, it relies on a singly-linked-list.  \nHowever, even with this optimization, the memory footprint of `LinkedQueue` is the highest (see the benchmark table below).  \n\n## Better implementations\n### Linked List of Ring Buffers\nA ring buffer, or a cyclic queue, is a *bounded* data structure that relies on an array. It's very fast, but bounded.  \nWe can, however, introduce a new data structure named `ChunkedQueue`, in which we create a `LinkedQueue` with each item in it to be a cyclic queue.  \n\n### DynamicCyclicQueue\nSame as a cyclic queue, but can exceed the initial length of the underlying array.  \nHow? when it's full, the next `enqueue` operation would trigger a re-order of the underlying array, and then would expand it with `push` operations.\nThis process is *O(1) amortized*, and therefore this is a generic queue, and can be used in any scenario.\n\n# The Benchmark\nFor a full deep dive of the scenarios, measurement and comparison with implementations (also external to this project),\nplease read [benchmarks.md](benchmarks.md) file.\n\n## Methodology\nThe scenario being checked is the following:  \nset P = 100000  \nenqueue 30P items  \ndequeue 5P  \ndo 6 times:  \n\u0026nbsp;\u0026nbsp;enqueue 1P  \n\u0026nbsp;\u0026nbsp;dequeue 5P  \n\nApply this scenario T times (set T=30) for every relevant class (see table below), measure RAM used and ops/sec.  \nTake the average (mean) of the results.\n\nNote: we took a very large value for P, otherwise complexity related issues won't come up.\n\n## Results\n| Class Name         | Ops/Sec | RAM used (MB) | \n|:-------------------|--------:|--------------:|\n| DynamicArrayQueue  |   **5** |             8 |\n| ChunkedQueue       |   36200 |        **28** |\n| DynamicCyclicQueue |   28200 |            89 |\n| LinkedQueue        |   21300 |           143 |\n\n## Analysis\n1. The naive implementation, `DynamicArrayQueue`, is so slow that it can't be considered as an option\n2. The fastest implementation is `ChunkedQueue`, and has the lowest RAM usage\n3. The common `LinkedQueue` implementation is not the fastest one, even with *O(1)* time complexity, and it's the most wasteful in terms of RAM usage\n\n## Suggestions\n* Use the provided `ChunkedQueue` for a generic solution\n\n## License\nMIT \u0026copy; Ron Klein\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkleinron%2Flite-fifo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkleinron%2Flite-fifo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkleinron%2Flite-fifo/lists"}