{"id":16831159,"url":"https://github.com/zbjornson/node-bswap","last_synced_at":"2025-06-27T11:41:40.925Z","repository":{"id":50934586,"uuid":"60220764","full_name":"zbjornson/node-bswap","owner":"zbjornson","description":"Fast byte swapping for Node.js and browsers","archived":false,"fork":false,"pushed_at":"2023-09-18T01:26:26.000Z","size":109,"stargazers_count":8,"open_issues_count":0,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-25T02:36:36.574Z","etag":null,"topics":["avx2","avx512","bswap","buffer","endianness","neon","nodejs","simd","ssse3","typedarray","x86"],"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/zbjornson.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":"2016-06-02T00:48:04.000Z","updated_at":"2024-08-08T00:34:59.000Z","dependencies_parsed_at":"2024-10-13T11:42:39.725Z","dependency_job_id":"d20799cc-f7f9-422c-b77f-5eaf48ae885f","html_url":"https://github.com/zbjornson/node-bswap","commit_stats":{"total_commits":57,"total_committers":2,"mean_commits":28.5,"dds":"0.052631578947368474","last_synced_commit":"d3fb5a0f3d9b564900c467d7327f5000bb132b78"},"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zbjornson%2Fnode-bswap","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zbjornson%2Fnode-bswap/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zbjornson%2Fnode-bswap/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zbjornson%2Fnode-bswap/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zbjornson","download_url":"https://codeload.github.com/zbjornson/node-bswap/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248340036,"owners_count":21087373,"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":["avx2","avx512","bswap","buffer","endianness","neon","nodejs","simd","ssse3","typedarray","x86"],"created_at":"2024-10-13T11:42:31.025Z","updated_at":"2025-04-11T04:20:28.772Z","avatar_url":"https://github.com/zbjornson.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# node-bswap\n\nx86: ![x86 Build Status](https://github.com/zbjornson/node-bswap/actions/workflows/ci.yaml/badge.svg)  \nARM: [![ARM Build Status](https://cloud.drone.io/api/badges/zbjornson/node-bswap/status.svg)](https://cloud.drone.io/zbjornson/node-bswap)\n\nThe fastest function to swap bytes (a.k.a. reverse the byte ordering, change\nendianness) of TypedArrays in-place for Node.js, Bun and browsers. Uses SIMD\nwhen available. Works with all of the TypedArray types, including BigUint64Array\nand BigInt64Array. Also works on Buffers if you construct a TypedArray view on\nthe underlying ArrayBuffer (see below).\n\nInstall:\n```\n$ npm install bswap\n$ bun install bswap  # but see https://bun.sh/guides/install/trusted\n```\n\nUse:\n```js\nimport bswap from \"bswap\";\nconst x = new Uint16Array([1, 2, 3, 4, 5, 6, 7, 8]);\nbswap(x);\n// now: Uint16Array [ 256, 512, 768, 1024, 1280, 1536, 1792, 2048 ]\n\n// With buffers:\nconst b = Buffer.alloc(128);\n// This constructs a \"view\" on the same memory; it does not allocate new memory:\nconst ui32 = new Uint32Array(b.buffer, b.byteOffset, b.byteLength / Uint32Array.BYTES_PER_ELEMENT);\nbswap(ui32);\n```\n\nIn Node.js/Bun when native code and a recent x86 or ARM processor is available,\nthis library uses the fastest available SIMD instructions ([PSHUFB (SSSE3) or\nVPSHUFB (AVX2)](http://www.felixcloutier.com/x86/PSHUFB.html), [REVn\n(NEON)](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0489h/Cihjgdid.html)),\nwhich process multiple array elements simultaneously.\n\nIn the browser or when native code is unavailable, this library falls back to\nthe fastest JavaScript implementation. The JavaScript implementation is also\nalways explicitly available:\n\n```js\nimport {js} from \"bswap\"; // Use javascript implementation explicitly\n```\n\n## Benchmarks\n\nShowing millions of elements processed per second when invoked with a\n10,000-element array. (Run the benchmark suite to see results for varying array\nlengths and other libraries.) Ran on an Intel i9-11900H 2.50 GHz processor (AVX2\nsupported) or Cavium ThunderX 2.0 GHz processor (ARM NEON); Node.js v16.x;\nWindows 11 (MSVC) or Ubuntu 20.04 (GCC, Clang). (Note that a 10,000-element\nInt16Array fits in L1 cache, whereas a 10,000-element Int32Array or Float64Array\ndoes not.)\n\n| compiler  |    C++ |   JS   | Native:JS | Node.js | Native:Node |\n| --------- | -----: | ---:   | --------: | ------: | ----------: |\n| **16 bit types (Uint16Array, Int16Array)**\n| MSVC 2022 | 46,221 |    722 |     64.0x |  18,213 |        2.5x |\n| GCC 9.4   | 40,945 |     〃 |     56.8x |  13,720 |        2.9x |\n| Clang 15  | 47,398 |     〃 |     65.6x |      〃 |        3.5x |\n| GCC-ARM   |  2,677 |    183 |     14.6x |     297 |        9.0x |\n| **32 bits types (Uint32Array, Int32Array, Float32Array)**\n| MSVC 2022 | 27,459 |    342 |     36.7x |   9,431 |        2.9x |\n| GCC 9.4   | 23,613 |     〃 |     61.9x |   2,842 |        8.3x |\n| Clang 15  | 29,013 |     〃 |     84.8x |      〃 |       10.2x |\n| GCC-ARM   |    670 |     94 |      7.1x |     249 |        2.7x |\n| **64 bit types (Float64Array)**\n| MSVC 2022 |  9,005 |    179 |     38.2x |   4,348 |        2.1x |\n| GCC 9.4   |  8,774 |     〃 |     49.1x |   2,642 |        3.3x |\n| Clang 15  |  8,937 |     〃 |     49.9x |      〃 |        3.4x |\n| GCC-ARM   |    382 |     49 |      7.8x |     213 |        1.8x |\n\nThere's an AVX512 implementation that is disabled by default. On the Cascade\nLake CPU that I tested on, it is ~28% faster than the AVX2 version when the data\nfit in the L1 cache. However, it is ~10% slower than the AVX2 version when the\ndata come from L2 and ~15% slower from L3. Under the assumption that this module\nis more often used with arrays larger than 32KB, I've thus left it disabled.\nSometime maybe I'll make it select between AVX2 and AVX512 depending on the\narray length, but this module has no ability to know if the data is resident in\nthe L1 cache.\n\n## Comparison to other libraries\n\n| Library | Operand | In-Place | 64-bit Type Support | Browser | Speed (vs. bswap)* |\n| --- | --- | --- | --- | --- | --- |\n| bswap (this) | TypedArray | yes | yes | yes | 1.00 |\n| node [`buffer.swap16/32/64`](https://nodejs.org/api/buffer.html#buffer_buf_swap16) | Buffer | yes | since 6.3.0 | no | 0.05 to 0.38 |\n| [network-byte-order](https://github.com/mattcg/network-byte-order) | Number/\\[Octet\\] | no | no | yes | 0.010 |\n| [endian-toggle](https://github.com/substack/endian-toggle) | Buffer | no | yes | no | 0.0056 |\n\n\\* Higher is better. For 16-bit types, 10k-element arrays. Range given for\nNode.js version reflects Windows vs. Linux benchmark.\n\n* **Node.js' built-in\n  [buffer.swap16|32|64](https://nodejs.org/api/buffer.html#buffer_buf_swap16)\n  methods** (16/32 since v5.10.0; 64 since 6.3.0). Operates in-place. No browser\n  support. Slower except for tiny arrays (where it uses the JS implementation).\n\n  In 6.3.0 I added some optimizations to Node.js' implementation. The\n  optimizations are effective on Windows, but GCC does not do the same automatic\n  vectorization that MSVC does, nor does Node's default build config enable the\n  newer SIMD instructions that this library uses.\n\n  \u003cdetails\u003e\u003csummary\u003eUsage\u003c/summary\u003e\n\n  ```js\n  \u003e Buffer.from(typedArray.buffer).swap16()\n  ```\n\n  \u003c/details\u003e\n\n* **[endian-toggle](https://github.com/substack/endian-toggle)**. Simple usage,\n  operates on a Node.js Buffer, handles any byte size, returns a new buffer\n  (does not operate in-place).\n\n  \u003cdetails\u003e\u003csummary\u003eUsage\u003c/summary\u003e\n\n  ```js\n  \u003e const x = new Uint16Array([2048])\n  \u003e toggle(Buffer.from(x.buffer), x.BYTES_PER_ELEMENT * 8)\n  \u003cBuffer d2 04 09 07\u003e\n  ```\n\n  \u003c/details\u003e\n\n* **[network-byte-order](https://github.com/mattcg/network-byte-order)**.\n  Operates on a single value at a time (i.e. needs to be looped to operate on an\n  array) and has separate `hton` and `ntoh` methods, which do effectively the\n  same thing but have different syntaxes. It can operate on strings, but it\n  cannot swap 64-bit types.\n\n  \u003cdetails\u003e\u003csummary\u003eUsage\u003c/summary\u003e\n\n  ```js\n  // Using hton\n  \u003e const b = [];\n  \u003e nbo.htons(b, 0, 2048);\n  \u003e b\n  [8, 0]\n  \n  // or using ntoh\n  \u003e const x = new Uint16Array([2048])\n  \u003e nbo.ntohs(new Uint8Array(x.buffer, x.byteOffset, 2), 0)\n  8\n  \u003e const z = new Uint16Array([8])\n  \u003e new Uint8Array(z.buffer, z.byteOffset, 2)\n  Uint8Array [ 8, 0 ]\n  ```\n\n  \u003c/details\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzbjornson%2Fnode-bswap","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzbjornson%2Fnode-bswap","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzbjornson%2Fnode-bswap/lists"}