Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/knut

knut

A pure-Rust columnar ↔ graph fabric — read/write Apache GraphAr, bulk-load FalkorDB, and serve Cypher over Arrow Flight SQL, with Bifröst streaming Iceberg tables into a live graph by CDC (Spark-Connect or Spark-free). One Arrow pipe from the lakehouse to a queryable graph.

⚡ part of the nordisk constellation

Mashup — one Arrow pipe: columnar lake → live graph

knut carries graph data the whole way from a columnar lake to a live, queryable graph in one Arrow pipe (no JVM required) — the rows marked NA are categories the rivals have no concept for:

capability knut GraphAr (official) Neo4j / GDS Spark + GraphFrames
Pure-Rust GraphAr — 5 formats (Parquet/CSV/ORC/JSON/Arrow), local or object store ✅ ◐ (C++/Java/Py) ✗ ◐
Cypher over Arrow Flight SQL server — ADBC / Power BI / DataFusion clients, Arrow out ✅ NA ◐ ✗
Iceberg → graph CDC fabric — snapshot-incremental + changelog (_change_type → MERGE / DETACH DELETE) ✅ NA ✗ ◐
Spark-free Iceberg ingestion (skade IcebergSource, no JVM) ✅ NA ✗ ✗
Bulk columnar RecordBatch → live graph DB (FalkorDB UNWIND/CREATE) ✅ ◐ ✅ ✅
Mature graph-algorithm library + production graph engine ◐ ✗ ✅ ✅

Rows marked NA: the rival has no such category. The measured numbers are below.

Benchmarks

v0.1.3 · oden · 32 cores · 2026-07-23

host oden · 32 cores
version 0.1.3
measured 2026-07-23
arms 29
borrowed arms 10 named nornir.* — measured here but owned by nornir
tests 29/29 passed
publishable yes
flagged implausible 2

⚠ 2 arms carrying a number that is not credible as real work. Each is marked ⚠ or withheld wherever it appears below — never published as a measurement:

arm what is not credible
bifrost_fabric rows_per_s = 6.698e9/s derived from a 1.49e-5 s interval — under the 1e-4 s timing floor, so the rate is arithmetic, not measurement
merge_property_groups rows_per_s = 1.067e10/s derived from a 9.37e-6 s interval — under the 1e-4 s timing floor, so the rate is arithmetic, not measurement

ℹ 10 arms in this run belong to another repo (10 × nornir.*). They are the harness's own suite, pulled in because the bench runner this repo pins predates the arm filter that would have excluded them — so they were measured here without being asked for. They describe nornir, not knut, and are shown separately below rather than mixed into this repo's numbers.

The Arrow pipe — knut's own arms

Storage formats round-tripped through the GraphAr writer/reader, the Bifröst CDC fabric, the FalkorDB bulk path, and the Thund streaming window operators.

v0.1.3 · oden · 32 cores · 2026-07-23

workload rows_per_s read_rows_per_s write_rows_per_s incremental_rows_per_s recompute_rows_per_s checkpointed_rows_per_s restore_resume_rows_per_s speedup_x telem_cores_busy_avg telem_elapsed_ms
builder_dump 1.42M 1 71.43
cypher_render 3.21M 1 38.22
doput_dispatch 0.85 1.60 4766
falkor_parallel_dispatch 29.75 1 801.77
file_source_scan 48.55M 1 20.62
format_arrow 170.32M 77.14M 1 10.89
format_csv 8.18M 5.44M 2 42.19
format_json 1.08M 8.44M 2 113.17
format_orc 63.84M 47.38M 1 12.46
format_parquet 45.57M 7.16M 2 24.88
graphar_vertex_load 35.85M 2 54.49
ingest_lifecycle 36.05M 2 24.69
thund_checkpoint 14.11M 2 157.51
thund_incremental_agg 6.13M 1.80M 1.50 1467
thund_recovery 33.59M 1 129.08
thund_watermark_drop 2.22M 3.81M 1 36.46
thund_window_close 16.58M 31.40M 1 193.79

⚠ withheld from this table — not credible as real work:

telem_cores_busy_avg is the average number of CPU cores busy while the arm ran — a single-digit value on a 32-core host means the arm is serial by construction, not that the box was idle. Blank cells are metrics that arm does not report.

Borrowed arms — nornir's own suite, measured here by accident

v0.1.3 · oden · 32 cores · 2026-07-23

workload elapsed_ms rows_per_sec queries_per_sec symbols_per_sec events_per_sec speedup_vs_full telem_cores_busy_avg
nornir.delta_rescan 8.19 2.70 0
nornir.dep_graph_build 24.07 365085 1
nornir.dep_graph_build_ext 31.88 344637 1
nornir.funnel_append 1284 49.84 1
nornir.funnel_append_batch 1.23 52137 0
nornir.knowledge_query 16.85 23742 1
nornir.knowledge_scan 1.78 674582 0
nornir.plan_dag_assemble 107.38 0
nornir.symbol_append 4.59 239618 0
nornir.warehouse_query 1.22 410561 0

These arms measure nornir, not knut. knut/xtask pins nornir = "0.5" from crates.io, and that published runner predates the NORNIR_BENCH_ONLY arm filter — so the filter was accepted and silently ignored, and nornir's suite ran alongside knut's. They are kept in their own table so they can never be read as knut's numbers; the fix is a newer runner, not an edit to this file.

SQL for Power BI lives next door (2026-09-09)

knut's Flight SQL server (graphar-flight) speaks Cypher — the graph. Power BI, the Arrow Flight SQL ODBC driver and ADBC speak SQL, and that dialect is skade-flight in the skade repo: DataFusion over the Iceberg warehouse, streamed Arrow, ODBC escapes translated, 129 Power Query statement shapes green. Two dialects, two services, one wire; korp mounts both. The knut bridge — graph tables as DataFusion table providers in that same session — is the next step, not done.

Read the real docs

Files

Newest commits