Open a CSV with a few million rows in a web app and the tab often freezes. In Node the same file can eat gigabytes of memory.
The usual cause: every row becomes a JavaScript object. Ten million rows means ten million small objects, each carrying its own keys, all parsed on one thread while the other cores sit idle.
A different layout
Vectro (vectrojs on npm) takes another route:
- each column is stored as one typed array in WebAssembly memory, not as objects
- the CSV is split into pieces and parsed on every core (worker threads in Node, Web Workers in the browser)
- you query it with SQL or a small expression API
Node
import { Engine, sql } from 'vectrojs';
const engine = new Engine();
const orders = engine.readCSV('orders.csv');
sql('SELECT region, SUM(price) AS revenue FROM orders GROUP BY region', { orders }).toRows();
Browser
import { Engine, sql } from 'vectrojs/browser';
const engine = new Engine();
const orders = await engine.loadCSV('/orders.csv');
await sql('SELECT region, SUM(price) AS revenue FROM orders GROUP BY region', { orders }).toRowsAsync();
Threads in the browser need the page to be cross-origin isolated (COOP/COEP headers). Without them SplitEngine still uses every core.
Numbers
On an M1 Pro laptop (8 cores):
| Task | Result |
|---|---|
| Parsing a CSV stream | 16.9M rows/s (plain Node: 3.26M) |
GROUP BY region on 10M rows |
6.5 ms (DuckDB on the same machine: 39.7 ms) |
The scripts behind these are in the repo under compare/ and bench/.
Try it
- In the browser, nothing to install: vectrojs.dev/playground. Drop in a CSV or generate up to 10M sample rows, then query it with SQL. The data stays in your tab.
npm i vectrojs
It's open source (pure JS + WebAssembly, no native build). Feedback and issues are welcome on GitHub.
Top comments (0)