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
Cvalues survives an edit that touches a fractionpof 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)
| File | Size | Uploaded | |
|---|---|---|---|
| genna-0.1.0.tar.gz | 160.2 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| 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 logRelease 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 logRelease 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 logRelease 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 logRelease 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 logRelease 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 logRelease 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 logRelease 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