[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-81580":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":13,"contributorsCount":13,"subscribersCount":13,"size":13,"stars1d":14,"stars7d":14,"stars30d":14,"stars90d":13,"forks30d":13,"starsTrendScore":15,"compositeScore":13,"rankGlobal":10,"rankLanguage":10,"license":16,"archived":17,"fork":17,"defaultBranch":18,"hasWiki":19,"hasPages":17,"topics":20,"createdAt":10,"pushedAt":10,"updatedAt":26,"readmeContent":27,"aiSummary":28,"trendingCount":13,"starSnapshotCount":13,"syncStatus":29,"lastSyncTime":30,"discoverSource":31},81580,"react-native-columnar","pioner92\u002Freact-native-columnar","pioner92","🚀 High-performance utility for zero-copy data transport from JSI C++ to JavaScript via columnar ArrayBuffer layout","",null,"TypeScript",25,0,1,3,"MIT License",false,"main",true,[21,22,23,24,25],"arraybuffer","binary","jsi","react-native","react-native-jsi","2026-06-12 02:04:17","\u003Cimg src=\".\u002Fassets\u002Fimg.webp\" alt=\"react-native-columnar\" \u002F>\n\n# react-native-columnar\n\n[![npm](https:\u002F\u002Fimg.shields.io\u002Fnpm\u002Fv\u002Freact-native-columnar)](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Freact-native-columnar)\n[![license](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Flicense-MIT-blue)](LICENSE)\n[![platform](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fplatform-iOS%20%7C%20Android-lightgrey)]()\n\nZero-copy columnar `ArrayBuffer` transport from JSI C++ to JavaScript.\n\nJSI modules often return datasets as arrays of objects — every row becomes a JS object, every value gets boxed, GC pressure grows. `react-native-columnar` packs all values into one binary buffer and exposes each column as a typed array view over the same memory. No objects, no parsing, no copy.\n\n---\n\n## ⚡ Benchmark\n\n10 000 iterations · 5 columns · iPhone 16 Pro\n\n```\nid (int32) | status (uint8) | isActive (uint8) | createdAt (double) | updatedAt (double)\n```\n\n| Rows | Array of objects | react-native-columnar | Speedup  |\n|------|------------------|-----------------------|----------|\n| 100  | ~418.81 ms       | **~14.96 ms**         | **27×**  |\n| 500  | ~2079.81 ms      | **~22.06 ms**         | **94×**  |\n| 1000 | ~4360.11 ms      | **~35.89 ms**         | **121×** |\n| 2000 | ~9444.47 ms      | **~45.39 ms**         | **208×** |\n\n---\n\n## 🎯 Best use cases\n\nSQLite result sets · Frame processor outputs · Sensor streams · Analytics events · Realtime charts · Large JSI payloads\n\n---\n\n## 📦 Installation\n\n```sh\nnpm install react-native-columnar\n# or\nyarn add react-native-columnar\n```\n\n**iOS** — headers are picked up automatically via CocoaPods.\n\n**Android — app project**\n\nAutolinking registers the package automatically. Add to `android\u002Fapp\u002Fbuild.gradle`:\n\n```groovy\nandroid {\n  buildFeatures { prefab true }\n}\n```\n\nThen in `CMakeLists.txt`:\n\n```cmake\nfind_package(react-native-columnar REQUIRED CONFIG)\ntarget_link_libraries(${YOUR_LIBRARY_NAME} react-native-columnar::react-native-columnar)\n```\n\n**Android — standalone library**\n\nAdd to `package.json`:\n\n```json\n{ \"dependencies\": { \"react-native-columnar\": \"*\" } }\n```\n\nThen in `CMakeLists.txt` (`NODE_MODULES_DIR` is already passed by any JSI library):\n\n```cmake\ninclude_directories(${NODE_MODULES_DIR}\u002Freact-native-columnar\u002Fcpp)\n```\n\nIn your C++ files:\n\n```cpp\n#include \"react-native-columnar.h\"\n```\n\n---\n\n## 🔧 C++ side\n\n### 1. Define a schema\n\n```cpp\n#include \"react-native-columnar.h\"\n\n#define USER_COLUMNS(X)       \\\n  X(int32_t, id)              \\\n  X(uint8_t, status)          \\\n  X(uint8_t, isActive)        \\\n  X(double,  createdAt)       \\\n  X(double,  updatedAt)\n\nDECLARE_BINARY_SCHEMA(UserSchema, USER_COLUMNS)\n```\n\nGenerates `UserSchema` with `columnCount`, `byteSize()`, and a `Columns` struct of `std::span` views.\n\n### 2. Write and return an ArrayBuffer\n\n```cpp\nusing namespace rn_columnar;\n\njsi::Value getUsers(jsi::Runtime& rt, const jsi::Value*, const jsi::Value* args, size_t) {\n  const uint32_t rows = static_cast\u003Cuint32_t>(args[0].asNumber());\n\n  ColumnarWriterBuilder\u003CUserSchema> builder(rows);\n  auto cols = UserSchema::createColumns(builder);\n\n  for (uint32_t i = 0; i \u003C rows; ++i) {\n    cols.id[i]        = dbRow[i].id;\n    cols.status[i]    = dbRow[i].status;\n    cols.isActive[i]  = dbRow[i].isActive;\n    cols.createdAt[i] = dbRow[i].createdAt;\n    cols.updatedAt[i] = dbRow[i].updatedAt;\n  }\n\n  return builder.toArrayBuffer(rt); \u002F\u002F zero-copy move into JSI\n}\n```\n\n---\n\n## 🟦 JS side\n\n### 1. Define the schema\n\nMust match column order and types from C++:\n\n```ts\nimport { createBufferReader, ColumnType } from 'react-native-columnar';\n\nconst USER_SCHEMA = [\n  ColumnType.Int32,    \u002F\u002F id\n  ColumnType.Uint8,    \u002F\u002F status\n  ColumnType.Uint8,    \u002F\u002F isActive\n  ColumnType.Float64,  \u002F\u002F createdAt\n  ColumnType.Float64,  \u002F\u002F updatedAt\n] as const;\n```\n\n### 2. Read the buffer\n\n```ts\nconst buffer: ArrayBuffer = __getUsers();\n\nconst [header, columns] = createBufferReader(buffer, USER_SCHEMA);\nconst [idCol, statusCol, isActiveCol, createdAtCol, updatedAtCol] = columns;\n\u002F\u002F idCol — Int32Array  |  statusCol — Uint8Array  |  createdAtCol — Float64Array\n\nconst id        = idCol[0];\nconst status    = statusCol[0];\nconst isActive  = isActiveCol[0];\nconst createdAt = createdAtCol[0];\nconst updatedAt = updatedAtCol[0];\n```\n\nAll columns are zero-copy typed array views — the buffer is never copied.\n\n### API\n\n```ts\ncreateBufferReader(buffer: ArrayBuffer, schema: readonly ColumnType[])\n  \u002F\u002F → [header: Int32Array, columns: TypedArray[]]\n  \u002F\u002F header[0] = row count, header[1] = column count\n```\n\n### ColumnType mapping\n\n| `ColumnType`      | C++ type    | JS view        | Bytes | Tip                           |\n|-------------------|-------------|----------------|-------|-------------------------------|\n| `Int8`            | `int8_t`    | `Int8Array`    | 1     |                               |\n| `Uint8`           | `uint8_t`   | `Uint8Array`   | 1     | bool, flags                   |\n| `Int16`           | `int16_t`   | `Int16Array`   | 2     |                               |\n| `Uint16`          | `uint16_t`  | `Uint16Array`  | 2     |                               |\n| `Int32`           | `int32_t`   | `Int32Array`   | 4     | id, count, enum               |\n| `Uint32`          | `uint32_t`  | `Uint32Array`  | 4     |                               |\n| `Float32`         | `float`     | `Float32Array` | 4     | screen coords (~7 sig. digits)|\n| `Float64`         | `double`    | `Float64Array` | 8     | timestamp, price              |\n\n---\n\n## 🗂 Memory management\n\n**Buffer ownership**\n\n`ColumnarWriterBuilder` allocates a `std::vector\u003Cuint8_t>` internally. Calling `toArrayBuffer(rt)` moves the vector into a `shared_ptr\u003CVectorBuffer>` (a `jsi::MutableBuffer` subclass) and hands it to the JSI runtime — the builder is empty after this call and must not be used again.\n\n**Lifetime on the JS side**\n\nThe JS runtime (Hermes \u002F V8) becomes the sole owner of the `ArrayBuffer`. All typed-array views returned by `createBufferReader` are zero-copy views over the same memory — each view holds an implicit reference to the `ArrayBuffer`.\n\nThe underlying `std::vector` is freed when **all** JS references are gone: the original `ArrayBuffer` object and every typed-array view derived from it. No explicit `free()` or reference counting is required.\n\n```\nColumnarWriterBuilder  →  toArrayBuffer()  →  shared_ptr\u003CVectorBuffer>\n                                                       ↑\n                              jsi::ArrayBuffer  ───────┘   (JSI runtime owns)\n                                    ↑\n                Int32Array \u002F Float64Array \u002F …            (views, no copy)\n\nAll JS refs dropped  →  GC  →  shared_ptr ref-count = 0  →  vector freed\n```\n\n**Practical rules**\n\n- Don't keep a typed-array view alive longer than needed — it pins the entire buffer in memory.\n- Don't call `toArrayBuffer()` more than once on the same builder.\n- Buffer size is fixed at construction time (`rows` passed to the builder constructor).\n\n---\n\n## ⚠️ Limitations\n\nDesigned for dense numeric data only. Strings, nullable values, nested objects, and variable-length fields are not supported natively — encode them as fixed-width columns using ids, offsets, or sentinel values.\n\n---\n\n## 🛠 Troubleshooting\n\n**`react-native-columnar.h` not found on Android** — check that `prefab true` is enabled and CMake links the package correctly.\n\n**`std::span` errors** — set C++20 on the target that includes the header.\n\n**`RangeError` in JS** — JS and C++ schemas are out of sync. Check column order and types match exactly (`int32_t` → `Int32`, `double` → `Float64`).\n\n**Values look shifted** — one wrong type shifts all following columns. Compare schemas line by line.\n\n---\n\n## Contributing\n\n- [Development workflow](CONTRIBUTING.md#development-workflow)\n- [Sending a pull request](CONTRIBUTING.md#sending-a-pull-request)\n- [Code of conduct](CODE_OF_CONDUCT.md)\n\n## License\n\nMIT\n","react-native-columnar 是一个用于在 JSI C++ 和 JavaScript 之间通过列式 ArrayBuffer 布局实现零拷贝数据传输的高性能工具。其核心功能包括将数据集打包成单一的二进制缓冲区，并以类型化数组视图的形式暴露给 JavaScript，从而避免了对象创建和解析过程中的性能开销。该库特别适用于需要高效处理大量数据的场景，如 SQLite 查询结果、帧处理器输出、传感器流、分析事件以及实时图表绘制等。采用 TypeScript 编写，并支持 iOS 和 Android 平台，能够显著提高数据传输效率，减少垃圾回收压力。",2,"2026-06-11 04:05:34","CREATED_QUERY"]