Skip to main content

Genna

A versioned data store that edits in place instead of rewriting: splice a byte range in O(log n), keep every version, get the old bytes back exactly.

MIT licensed. One package, no dependencies, no build step. LICENSE


Install

pip install genna

The wheel ships the engine as a prebuilt shared library, so there is no compiler step and pip list shows exactly one package.

Requirements: Python 3.9+, on Linux (x86-64, arm64), macOS (Intel, Apple silicon) or Windows (x64). If no wheel matches your platform, pip falls back to the sdist, which builds the C engine and needs a compiler (build-essential, Xcode CLT, or MSYS2 mingw-w64).


See it work

genna-example

Fifty lines, no benchmarks, nothing to configure. It ships inside the package, so that command works straight after pip install genna — or run examples/time_travel.py from a checkout, which calls the same code. It writes a short document, edits it three times, then goes back:

Wrote the first draft: 201 bytes, version 0.

Edit 1 - replaced the closing lines.        now version 1, 158 bytes
Edit 2 - added a title at the top.          now version 2, 173 bytes
Edit 3 - appended a closing line.           now version 3, 199 bytes

The notebook now has 4 versions and it never rewrote the file.

Here is version 0 again, straight out of the store:
...
Identical to what was written? True

What changed between version 2 and version 3?
  bytes  128-192  really changed:  doors down. I write until the light chan...
  (1 windows were skipped without reading a single byte)

Rolling back to version 1...
  content now matches version 1 exactly:    True
  and the history still holds every step:   5 versions

In code, that is the whole surface:

import genna

e = genna.Engine()
o = e.create("train", open("data.jsonl", "rb").read())

o.update(1000, 20, b"corrected label")   # splice: O(log n), not a rewrite
o.update(5000, 0, b"appended record\n")

e.save("train.genna")                    # snapshot + write-ahead log

Every version stays addressable, and reopening gets the bytes back exactly:

e = genna.open_store("train.genna")
o = e["train"]

o.read()                 # latest
o.versions[0].bytes()    # the original, byte-for-byte
len(o.versions)          # 3

There is also a packaged tour of the dataset layer, which generates its own data and runs in about ten seconds:

genna-demo

The rule that decides whether it helps you

Genna stores data as content-addressed chunks in a persistent tree. An edit copies the path to the change and shares everything else, so a new version costs the size of the change, not the size of the data.

That gives one rule, and it is the only thing you need to predict whether Genna is worth your time:

A chunk of C values survives an edit that touches a fraction p of values with probability (1 − p)^C.

Sparse changes win. Fix 200 labels in a 5 GB dataset, retrain one region of a mesh, append to a log, patch a column: p is tiny, almost every chunk survives, and the new version costs kilobytes.

Diffuse changes do not. Re-quantize every row, apply an Adam step to every weight, re-encode a whole video: p ≈ 1, no chunk survives, and Genna stores a second copy while a plain file would have stored one. It is worse than doing nothing in that regime, and §"What it's bad at" has the measurement.

This is not a caveat hiding at the bottom of the page. It is the whole design.


What it's bad at

Full-precision model checkpoints — it does not work. Nine checkpoints of a 2M-parameter model under Adam: 0.00% of weights are byte-identical between consecutive steps, because momentum moves every parameter that gets any gradient. Genna lands at 0.9×worse than storing each checkpoint whole — and git beats both. It only works where parameters receive no gradient: LoRA 7.6×, frozen layers 2.8×. If you came here for checkpoint dedup on full fine-tunes, it will not help you.

Geometry compression — Draco wins, decisively. 2.07 B/vertex vs Genna's 12.00 in quantized mode, at lower error. Genna's advantage on 3D is version history of an evolving mesh, not compressing one mesh. Use Draco for the latter.

Memory-mapped stores are 3.29× bigger on disk. Zero-copy mmap means giving up whole-payload compression: 385 MB on disk for a 96 MB payload. You trade disk for not being bounded by RAM. Choose per store.

Merge refuses more than it should. Three-way merge is byte-exact on disjoint edits and correctly refuses overlapping ones, but each side's change is reduced to one contiguous span, so two sides that each made scattered edits get reported as conflicting when a finer differ would have merged them.

One machine. There is no replication, no server, no distributed story. Multi-writer is optimistic concurrency against a local file plus an advisory lock.

Every number here is a benchmark. No team has run this on their own corpus. That is the largest unknown and no amount of further engineering fixes it.


Four numbers

All measured on one machine, one run, against the real tools — not against a model of them. Full method, and every number that came out worse than I first reported it, in TEST_REPORT.md.

Genna the tool it replaces
Edit 1 sample in a 36,718-sample dataset 88 KB written MosaicML Streaming, 103 MB (shard rewrite) 1,170× less, 689× faster
Sync 100 scattered edits in a 10 MB file 34,246 B on the wire rsync 3.4.4, 342,051 B 10.0× less
Storage growth per commit, 8 MB source tree 110 B/commit git 2.55 after gc --aggressive, 872 B 7.9× less
Open a 770 MB store (Windows) 9.8 MB resident, 14 ms reading it in, 777 MB, 4,066 ms 79× less RAM

The git row compares against a repacked repo, with delta compression fully on. Comparing against loose objects would have shown ~23,000× and meant nothing.

The mmap row depends on both platform and payload size, so it needs qualifying. 79× is Windows, at a 770 MB store. The same comparison at an 8 MB payload measures 43.9× on Linux and 18.7× on macOS. The ratio grows with store size, because what is saved is the payload you never fault in while the fixed cost stays flat. Quote it with its platform and its size or it means very little — and until 15 August 2026 the macOS figure could not have been measured at all, because the resident-memory probe returned 0 on that platform without saying so (error −1.5 in TEST_REPORT.md).


Errors found in my own measurements

Fifteen so far, each one listed in TEST_REPORT.md §5 with what it changed. Every one of them was in Genna's favour before correction, which is the pattern worth knowing about. The three most useful:

CI had never run. The workflow triggered on main; the default branch is master. The project presented as continuously tested for its entire public life while running nothing. First real run: red on 7 of 8 jobs.
The gate skipped a third of the Python suite and exited 0. Missing extras printed SKIP and counted as passing. Skips are now failures.
The macOS memory probe returned 0 for every reading. /proc/self/statm does not exist there, so a measurement that could not be taken returned a number that looks like one.

Modules

Genna is the core. Adapters sit on top, and the core never imports them.

module status
genna (core engine) shipping
genna.dataset (curation) shipping — this is genna-curate
genna.mapped (out-of-core) shipping
genna.table / genna.sketch shipping, marked unstable
langgraph-checkpoint-genna in development, separate repository
genna.sweep, genna.kv, genna.config, genna.sync not built

The last row is named rather than omitted. A repository advertising seven modules with one working module reads as vapour; saying which ones do not exist costs nothing and is the honest version.

The architectural rule, while it is still true and cheap to keep: adapters depend on the core, the core depends on nothing, and every adapter writes the same file format. A store written by one adapter opens in another.


On-disk format and compatibility

The store carries a magic and an explicit format version, currently v3.

  • Opening a store written by a newer Genna fails with a message naming both versions, rather than misparsing it.
  • Opening a file that is not a Genna store says so, and a truncated store says something different again. Three outcomes, three messages.
  • genna.format_version() reports what this build writes; genna.store_format(path) reports what a file on disk is.

The policy, in plain words:

Within 0.x, the on-disk format may change. Every change bumps the version, and ships either a converter or an explicit refusal that names the versions involved — never a silent misread. From 1.0, the format is stable and stores written by any 1.x release stay readable by later 1.x releases.

The mechanism behind that promise is python/tests/test_format_stability.py, which opens a committed fixture store and compares every version byte-for-byte against a manifest recorded when it was written. If the format drifts, that test fails on the machine that changed it.


API stability

Every public name is marked stable or unstable. There is no unmarked name, and that is enforced rather than promised: python/tests/test_api_stability.py fails if a public name has no mark, if a mark outlives the name it described, or if anything marked stable has no test exercising it.

  • stable — covered by a test; will not change shape within 0.x.
  • unstable — may change or disappear in any 0.x release without a major bump. Usable, but pin your version.

Python: Engine, Object, Version, GennaError, open, open_store, Dataset, format_version, store_format are stable. Table, Schema, Record, Stats are unstable. The live table is genna.__stability__.

C: see the stability section at the top of include/genna.h. The CRUD, persistence and history calls are stable; gn_ext_*, gn_net_*, gn_dict_* and the token layer are not.

When in doubt a name is marked unstable. Unstable-and-honest beats stable-and-regretted.


Curating a dataset

Engine is the byte-level layer. For datasets you work in records, not offsets — examples/curate_a_dataset.py is runnable and prints exactly this:

ds = genna.Dataset.from_jsonl("train.jsonl")   # 5,500 records, 0.43 MB

ds.filter_length(min_bytes=60)                 # removed 120
ds.drop_containing("LOREM IPSUM")              # removed  80
ds.dedup()                                     # removed 300

ds.engine.save("train.genna")
store: 0.07 MB on disk, holding ALL 501 versions
  (the raw file alone was 0.43 MB, and that is one version)

Every intermediate state is addressable, and reopening gets the exact bytes:

ds2 = genna.Dataset.open("train.genna")
ds2.version_bytes(0) == open("train.jsonl", "rb").read()   # True
ds2.rollback(step.version_before)                          # undo one step

Each removed record is its own version, which is what makes rollback fine-grained — three curation steps became 501 versions.

Optional extras, none of them needed for the above:

pip install "genna[table]"      # columnar tables (pyarrow)
pip install "genna[semantic]"   # embedding near-dedup (onnxruntime)

Building from source

git clone https://github.com/4747uwu/GENNA
cd GENNA
make ci          # builds the engine and runs the C test suite
pip install .    # builds and installs the Python package

The full gate — sanitizers, fuzz campaigns, crash recovery, the benchmarks above — is bash tools/run_all.sh, which writes test-logs/. It is MSYS2/ Windows-specific; make ci is the portable subset.

What has actually been verified on which platform

The correctness suites pass on Linux, macOS and Windows, on machines nobody here owns — run 31900068263, 8 of 8 jobs green, commit b993f24:

status
C engine — Linux, macOS (incl. ASan + UBSan) passing
Python suite — Linux, macOS, Windows × 3.9, 3.12 passing
Build a wheel, install that, run the example from outside the repo passing
Every benchmark number quoted above Windows only, not independently reproduced

One caveat that belongs here rather than buried. CI installs zlib and zstd on Linux and macOS but not on Windows, so the Windows build has no compression — and a store written by a compressed build cannot be opened by a build without that codec. Genna says so plainly when it happens (it names the codec rather than calling your file damaged), but until Windows CI gets zstd, stores are not freely portable between platform builds of the same release. If you move stores between machines, check genna.open_store succeeds on both, or save with raw=True.

That last row is the important one. CI proves the engine is correct elsewhere; it does not re-measure the ratios. Treat every performance figure in this README as a measurement from a single Windows machine until it is reproduced on yours.


Documentation

TEST_REPORT.md Every measured number, plus the errors I made measuring them
PERSISTENCE.md On-disk format, crash guarantees, out-of-core, and what is not handled
MERGE.md Three-way merge and exactly when it refuses
AGGREGATES.md O(log n) range aggregates, and what they cost out-of-core
SPATIAL.md 3D/mesh results, including the ones that failed

Status

Alpha (0.1.0). The on-disk format is at v3; see the compatibility policy above for what that promises and what it does not.

License

MIT — see LICENSE.

Release files for genna 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for genna 0.1.0
File Size Uploaded
genna-0.1.0.tar.gz 160.2 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for genna 0.1.0
File
genna-0.1.0-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details
genna-0.1.0-py3-none-musllinux_1_2_x86_64.whl Python 3 none Linux musl 1.2+ x86-64 Details
genna-0.1.0-py3-none-musllinux_1_2_aarch64.whl Python 3 none Linux musl 1.2+ ARM64 Details
genna-0.1.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl Python 3 none Linux glibc 2.17+ x86-64 Details
genna-0.1.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl Python 3 none Linux glibc 2.17+ ARM64 Details
genna-0.1.0-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details
genna-0.1.0-py3-none-macosx_10_9_x86_64.whl Python 3 none macOS 10.9+ x86-64 Details

Total release size: 2.5 MB

Release files / genna-0.1.0.tar.gz

Download URL genna-0.1.0.tar.gz
Size 160.2 kB
Tags Source
SHA-256 checksum
How to use checksums
c00f2584a01fdb9afc5ef62ab684de78b94606d90342f038a70cf647d0ec1bac
BLAKE2b-256 checksum
How to use checksums
840c0e32f8dd5fdff013a52e79aa01f70b8f3514844a09b03b68ea2bc60607a0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 16, 2026.

Transparency log

Release files / genna-0.1.0-py3-none-win_amd64.whl

Download URL genna-0.1.0-py3-none-win_amd64.whl
Size 159.3 kB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
3bf5d4339981260f6a5c7ecec4a2a188e72f9dd3fcefab595d922a2894c4a46c
BLAKE2b-256 checksum
How to use checksums
b0220266202991d82a87fefea183397a2fa0562d6ff08cba63d23c8f5930edc4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 16, 2026.

Transparency log

Release files / genna-0.1.0-py3-none-musllinux_1_2_x86_64.whl

Download URL genna-0.1.0-py3-none-musllinux_1_2_x86_64.whl
Size 462.2 kB
Tags Linux musl 1.2+ x86-64 Python 3
SHA-256 checksum
How to use checksums
5129981aa0695df5c7eef5716d886b893e03adeff5a4fd6dad895cbfb0aa4e92
BLAKE2b-256 checksum
How to use checksums
7c14290cbf12467552bc0f131858f1ceacd12bf1a714361a9e8c2d910e75d45e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 16, 2026.

Transparency log

Release files / genna-0.1.0-py3-none-musllinux_1_2_aarch64.whl

Download URL genna-0.1.0-py3-none-musllinux_1_2_aarch64.whl
Size 454.6 kB
Tags Linux musl 1.2+ ARM64 Python 3
SHA-256 checksum
How to use checksums
fda9ea5c30c439272834398ad8b83c1180980809ccd54d0ec89670664992227b
BLAKE2b-256 checksum
How to use checksums
9b30fea2fc4f2b2a1d90664f442b854d81ccb6e1f14d0cfce8ecd965321ac15c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 16, 2026.

Transparency log

Release files / genna-0.1.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL genna-0.1.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 414.5 kB
Tags Linux glibc 2.17+ x86-64 Python 3
SHA-256 checksum
How to use checksums
c56fac1aa7a42e313dc9d8759acfad58c75badb3e116338b6199d3a079a45fec
BLAKE2b-256 checksum
How to use checksums
7441d4d8c348687b169343a06b8129dab63a773bbe327676a8547e628f5f828b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 16, 2026.

Transparency log

Release files / genna-0.1.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL genna-0.1.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 383.3 kB
Tags Linux glibc 2.17+ ARM64 Python 3
SHA-256 checksum
How to use checksums
500d24e6df1994913bd521807a3589d606fc2befd687cf7e8e833ffdf4519b61
BLAKE2b-256 checksum
How to use checksums
19f6a1613530f397ad242d40e16441d67756e13de7ff6c9407234bfeb3461e6d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 16, 2026.

Transparency log

Release files / genna-0.1.0-py3-none-macosx_11_0_arm64.whl

Download URL genna-0.1.0-py3-none-macosx_11_0_arm64.whl
Size 82.1 kB
Tags Python 3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
bee6add198b233cd0e8d0fc548698f2f8055f7a8aaabdb21611f3d44fdb23803
BLAKE2b-256 checksum
How to use checksums
998d9cf273a4b9bd5d48db8e43c895856791a4114f34d8e5488c5e3923bedb3f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 16, 2026.

Transparency log

Release files / genna-0.1.0-py3-none-macosx_10_9_x86_64.whl

Download URL genna-0.1.0-py3-none-macosx_10_9_x86_64.whl
Size 334.9 kB
Tags Python 3 macOS 10.9+ x86-64
SHA-256 checksum
How to use checksums
0b4f5d5b44ba35ec2a0bc9e38dfeec3b7cb27d4d022db4dae1b1418fa005449f
BLAKE2b-256 checksum
How to use checksums
d7feb9cb815b6db99f613025e8d1e4cd73c15fc995e0b8631cb88d22fc2ca400
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 16, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

8 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page