npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-native-columnar

v0.1.2

Published

High-performance utility for zero-copy data transport from JSI C++ to JavaScript via columnar ArrayBuffer layout.

Readme

react-native-columnar

npm license platform

Zero-copy columnar ArrayBuffer transport from JSI C++ to JavaScript.

JSI 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.


⚡ Benchmark

10 000 iterations · 5 columns · iPhone 16 Pro

id (int32) | status (uint8) | isActive (uint8) | createdAt (double) | updatedAt (double)

| Rows | Array of objects | react-native-columnar | Speedup | |------|------------------|-----------------------|----------| | 100 | ~418.81 ms | ~14.96 ms | 27× | | 500 | ~2079.81 ms | ~22.06 ms | 94× | | 1000 | ~4360.11 ms | ~35.89 ms | 121× | | 2000 | ~9444.47 ms | ~45.39 ms | 208× |


🎯 Best use cases

SQLite result sets · Frame processor outputs · Sensor streams · Analytics events · Realtime charts · Large JSI payloads


📦 Installation

npm install react-native-columnar
# or
yarn add react-native-columnar

iOS — headers are picked up automatically via CocoaPods.

Android — app project

Autolinking registers the package automatically. Add to android/app/build.gradle:

android {
  buildFeatures { prefab true }
}

Then in CMakeLists.txt:

find_package(react-native-columnar REQUIRED CONFIG)
target_link_libraries(${YOUR_LIBRARY_NAME} react-native-columnar::react-native-columnar)

Android — standalone library

Add to package.json:

{ "dependencies": { "react-native-columnar": "*" } }

Then in CMakeLists.txt (NODE_MODULES_DIR is already passed by any JSI library):

include_directories(${NODE_MODULES_DIR}/react-native-columnar/cpp)

In your C++ files:

#include "react-native-columnar.h"

🔧 C++ side

1. Define a schema

#include "react-native-columnar.h"

#define USER_COLUMNS(X)       \
  X(int32_t, id)              \
  X(uint8_t, status)          \
  X(uint8_t, isActive)        \
  X(double,  createdAt)       \
  X(double,  updatedAt)

DECLARE_BINARY_SCHEMA(UserSchema, USER_COLUMNS)

Generates UserSchema with columnCount, byteSize(), and a Columns struct of std::span views.

2. Write and return an ArrayBuffer

using namespace rn_columnar;

jsi::Value getUsers(jsi::Runtime& rt, const jsi::Value*, const jsi::Value* args, size_t) {
  const uint32_t rows = static_cast<uint32_t>(args[0].asNumber());

  ColumnarWriterBuilder<UserSchema> builder(rows);
  auto cols = UserSchema::createColumns(builder);

  for (uint32_t i = 0; i < rows; ++i) {
    cols.id[i]        = dbRow[i].id;
    cols.status[i]    = dbRow[i].status;
    cols.isActive[i]  = dbRow[i].isActive;
    cols.createdAt[i] = dbRow[i].createdAt;
    cols.updatedAt[i] = dbRow[i].updatedAt;
  }

  return builder.toArrayBuffer(rt); // zero-copy move into JSI
}

🟦 JS side

1. Define the schema

Must match column order and types from C++:

import { createBufferReader, ColumnType } from 'react-native-columnar';

const USER_SCHEMA = [
  ColumnType.Int32,    // id
  ColumnType.Uint8,    // status
  ColumnType.Uint8,    // isActive
  ColumnType.Float64,  // createdAt
  ColumnType.Float64,  // updatedAt
] as const;

2. Read the buffer

const buffer: ArrayBuffer = __getUsers();

const [header, columns] = createBufferReader(buffer, USER_SCHEMA);
const [idCol, statusCol, isActiveCol, createdAtCol, updatedAtCol] = columns;
// idCol — Int32Array  |  statusCol — Uint8Array  |  createdAtCol — Float64Array

const id        = idCol[0];
const status    = statusCol[0];
const isActive  = isActiveCol[0];
const createdAt = createdAtCol[0];
const updatedAt = updatedAtCol[0];

All columns are zero-copy typed array views — the buffer is never copied.

API

createBufferReader(buffer: ArrayBuffer, schema: readonly ColumnType[])
  // → [header: Int32Array, columns: TypedArray[]]
  // header[0] = row count, header[1] = column count

ColumnType mapping

| ColumnType | C++ type | JS view | Bytes | Tip | |-------------------|-------------|----------------|-------|-------------------------------| | Int8 | int8_t | Int8Array | 1 | | | Uint8 | uint8_t | Uint8Array | 1 | bool, flags | | Int16 | int16_t | Int16Array | 2 | | | Uint16 | uint16_t | Uint16Array | 2 | | | Int32 | int32_t | Int32Array | 4 | id, count, enum | | Uint32 | uint32_t | Uint32Array | 4 | | | Float32 | float | Float32Array | 4 | screen coords (~7 sig. digits)| | Float64 | double | Float64Array | 8 | timestamp, price |


⚠️ Limitations

Designed 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.


🛠 Troubleshooting

react-native-columnar.h not found on Android — check that prefab true is enabled and CMake links the package correctly.

std::span errors — set C++20 on the target that includes the header.

RangeError in JS — JS and C++ schemas are out of sync. Check column order and types match exactly (int32_tInt32, doubleFloat64).

Values look shifted — one wrong type shifts all following columns. Compare schemas line by line.


Contributing

License

MIT