Skip to main content

deepdiff-rs

CI coverage PyPI downloads license last commit

onix is a Rust rewrite of Python DeepDiff's core: byte-compatible output, 37-4588x faster, with ignore_order support included. Install it as deepdiff-rs, a drop-in DeepDiff class for Python, or run the diff engine as the onix command-line tool.

deepdiff-rs reads live Python objects (or JSON) and produces the exact same report DeepDiff does at verbose_level=2, so it slots into code that already parses DeepDiff output while running dramatically faster on large or deeply nested inputs.

Status (September 2026): deepdiff-rs 0.x is live on PyPI (Python 3.9+, wheels for Linux x86_64/aarch64, macOS arm64/x86_64, and Windows x64, plus an sdist); the onix CLI builds from source, and nothing is on crates.io yet. Ordered and ignore_order diffing are complete, differentially tested against real DeepDiff 9.1.0, and benchmarked. It is 0.x, not stable or 1.0: the API may still change before 1.0.

Table of contents

Install

Python (the deepdiff-rs package, import name deepdiff_rs):

pip install deepdiff-rs

From source:

cd crates/onix-py
uv tool install maturin              # the build tool (skip if already installed)
uv sync --group test                 # creates .venv, installs pytest + pinned deepdiff
uv run --group test maturin develop --release

CLI (the onix binary), from a clean clone:

cargo install --path crates/onix-cli

Library crate (onix-core), a path dependency only (it sets publish = false):

[dependencies]
onix-core = { path = "crates/onix-core" }

Quickstart

The drop-in DeepDiff class, on live Python objects:

from deepdiff_rs import DeepDiff

diff = DeepDiff({"a": 1}, {"a": 2})
if diff:
    print(diff.to_json())   # byte-compatible with DeepDiff(...).to_json() at verbose_level=2
    print(diff.to_dict())   # the same report as a native Python dict
{"values_changed":{"root['a']":{"new_value":2,"old_value":1}}}
{'values_changed': {"root['a']": {'new_value': 2, 'old_value': 1}}}

diff_json, the fast path when you already have JSON text (it parses, diffs, and serializes entirely in Rust, with no Python-object conversion):

from deepdiff_rs import diff_json

print(diff_json('{"a": 1}', '{"a": 2}'))
{"values_changed":{"root['a']":{"new_value":2,"old_value":1}}}

The onix CLI, diffing two JSON files (compact JSON to stdout, {} for no differences):

$ echo '{"a": 1}' > left.json
$ echo '{"a": 2}' > right.json
$ onix diff left.json right.json
{"values_changed":{"root['a']":{"new_value":2,"old_value":1}}}

Pass --ignore-order to compare every list by value instead of by position, mirroring DeepDiff(..., ignore_order=True).

Known limitations

  • Only the core diff is implemented: exclude_paths, significant_digits, custom operators, verbose_level != 2, and delta/patch are not (yet) supported.
  • Supported value types are None, bool, int, float, str, dict (with str keys), and list; ints must fit in i64/u64, floats must be finite, and anything else (tuple, set, date, custom object, non-str dict key) raises TypeError or ValueError naming the exact path it was found at. See crates/onix-py/src/convert.rs.
  • Adversarially deep input raises MaxDepthError instead of crashing: the default max_depth is 512 and the hard ceiling is MAX_DEPTH_CEILING (20,000). See crates/onix-py/src/guard.rs.
  • ignore_order pairing is O(N^2) in unpaired elements per side and carries a polynomial cost in both time and memory with input depth; it has no max_passes/max_diffs cutoff, so bound the size and depth of untrusted input yourself. See crates/onix-core/src/ignore_order/mod.rs.
  • Output is byte-identical to DeepDiff except for one boundary case: integers past 2^53 (the limit of exact f64 representation) inside ordered scalar lists. See tests/golden/README.md.

Performance

Two committed, regenerable reports back the numbers below; every figure here is copied verbatim from them.

The Python bindings against real deepdiff on live Python objects, the number a real caller pays (source: crates/onix-py/benchmarks/bench_bindings.py, macOS 26.5.1, Apple M5 Max, median of 11 isolated subprocess runs per side):

Shape deepdiff deepdiff_rs Speedup
ignore_order, 10k shuffled ints, ~5% mutated (live objects) 3128.94ms 82.57ms 37.89x
  peak RSS 228.0 MB 141.2 MB 1.61x
  CPU seconds 3.128 s 0.083 s 37.88x
Heterogeneous API-payload records, n=20,000 (live objects) 3466.52ms 149.18ms 23.24x
  peak RSS 117.5 MB 148.3 MB 0.79x
  CPU seconds 3.465 s 0.149 s 23.24x
Same ignore_order shape, via diff_json (JSON-string path) 3133.45ms 83.16ms 37.68x
  peak RSS 228.9 MB 141.7 MB 1.62x
  CPU seconds 3.131 s 0.083 s 37.68x
Same API-payload shape, via diff_json (JSON-string path) 4568.33ms 86.33ms 52.92x
  peak RSS 139.0 MB 141.7 MB 0.98x
  CPU seconds 4.566 s 0.086 s 52.90x
Same API-payload shape, both tools reading two JSON files from disk 4571.28ms 85.35ms 53.56x
  peak RSS 139.0 MB 141.8 MB 0.98x
  CPU seconds 4.569 s 0.085 s 53.54x

The engine's own diff-only time and peak resident memory against pinned deepdiff 9.1.0 (source: perf/RESULTS.md, same machine, median over tier-appropriate runs, diff time excluding process startup and JSON parsing on both sides):

Fixture onix diff-only (median, min-max) deepdiff diff-only (median, min-max) Speedup onix peak RSS deepdiff peak RSS Memory ratio ≥5x threshold
flat_dict_10k 3.093 ms (3.020 ms-3.153 ms) 143.691 ms (140.322 ms-145.891 ms) 46.46x 5.72 MB 39.46 MB 6.90x
flat_dict_100k 38.354 ms (37.963 ms-38.916 ms) 1.596 s (1.584 s-1.686 s) 41.60x 40.53 MB 110.95 MB 2.74x
flat_dict_1m 450.356 ms (449.689 ms-467.911 ms) 16.936 s (16.889 s-17.154 s) 37.60x 478.10 MB 753.75 MB 1.58x
flat_list_100k 81.787 ms (78.266 ms-89.593 ms) 4.798 s (4.746 s-4.828 s) 58.67x 38.16 MB 155.11 MB 4.06x
nested_uniform_d6_b10 208.770 ms (208.269 ms-209.842 ms) 71.500 s (71.498 s-72.875 s) 342.48x 224.58 MB 908.33 MB 4.04x
api_payloads 160.667 ms (153.309 ms-171.032 ms) 94.138 s (93.625 s-94.669 s) 585.92x 269.39 MB 544.98 MB 2.02x
deep_narrow_d120 0.027 ms (0.026 ms-0.028 ms) 123.792 ms (123.234 ms-124.809 ms) 4588.45x 2.18 MB 41.08 MB 18.85x
startup_trivial 0.001 ms (0.001 ms-0.001 ms) 0.181 ms (0.174 ms-0.207 ms) 177.24x 2.18 MB 32.69 MB 15.00x
ignore_order_10k 80.965 ms (80.117 ms-83.510 ms) 13.010 s (12.900 s-13.023 s) 160.68x 108.82 MB 345.41 MB 3.17x
identical_1m 6.996 ms (6.114 ms-7.731 ms) 15.853 s (15.773 s-16.021 s) 2266.18x 315.39 MB 503.28 MB 1.60x

Both reports carry their full methodology, fairness rules, and the reproduce command. perf/RESULTS.md is an upper bound (JSON parsed straight into the engine, no Python-object conversion); the bindings table is the product-surface number. Regenerate them with perf/run_bench.sh and crates/onix-py/benchmarks/bench_bindings.py (see CONTRIBUTING.md).

Reference

Python API. The public surface is DeepDiff, diff_json, MaxDepthError, and MAX_DEPTH_CEILING.

  • DeepDiff(t1, t2, ignore_order=False, max_depth=None): diffs two live Python objects; .to_json() returns the DeepDiff-compatible JSON string, .to_dict() the same report as a dict, and the instance is falsy when there is no difference.
  • diff_json(a, b, ignore_order=False, max_depth=None) -> str: diffs two JSON strings entirely in Rust and returns the report as a JSON string.
  • MaxDepthError (a ValueError subclass) is raised when input exceeds max_depth; MAX_DEPTH_CEILING (20,000) is the hard upper bound on max_depth.

CLI. onix diff <a.json> <b.json> [--max-depth N] [--ignore-order] [--timing] reads both files as JSON and prints a compact, single-line DeepDiff-compatible report to stdout ({} when there is no difference).

  • --max-depth N overrides the recursion-depth bound (default: the ONIX_MAX_DEPTH environment variable if set, else 512).
  • --ignore-order compares every list/tuple by hash-based matching instead of by position, mirroring DeepDiff(..., ignore_order=True).
  • --timing prints one line of JSON ({"parse_ns": N, "diff_ns": N}) to stderr.

Exit codes:

Code Meaning
0 Diff computed successfully (whether or not the report is empty; differences are carried in the stdout JSON, not the exit code).
1 Usage error (missing/unknown subcommand, wrong argument count, unknown flag, non-numeric --max-depth); details and a usage line go to stderr.
2 I/O error (e.g. a missing input file) or a JSON-parse error on either input.
3 max_depth exceeded; the path that tripped the bound goes to stderr.

Layout

crates/onix-core   # the diff engine (library, no I/O)
crates/onix-cli    # the `onix` binary (thin CLI over the core)
crates/onix-py     # PyO3 bindings, published as `deepdiff-rs`
scripts/           # gen_goldens.py: regenerates tests/golden/ from real DeepDiff
tests/golden       # DeepDiff-generated expected outputs (the compatibility corpus)
perf/              # cross-language benchmark harness and RESULTS.md

Contributing

Issues and pull requests are welcome. Open an issue to report a bug, a DeepDiff divergence (include both inputs and the report each engine produces), or a question. Building from source, the quality gates, the golden corpus, benchmarking, mutation testing, and publishing are all in CONTRIBUTING.md.

License

MIT: see LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

deepdiff_rs-0.3.1.tar.gz (160.9 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

deepdiff_rs-0.3.1-cp39-abi3-win_amd64.whl (348.3 kB view details)

Uploaded CPython 3.9+Windows x86-64

deepdiff_rs-0.3.1-cp39-abi3-manylinux_2_28_x86_64.whl (450.3 kB view details)

Uploaded CPython 3.9+manylinux: glibc 2.28+ x86-64

deepdiff_rs-0.3.1-cp39-abi3-manylinux_2_28_aarch64.whl (431.2 kB view details)

Uploaded CPython 3.9+manylinux: glibc 2.28+ ARM64

deepdiff_rs-0.3.1-cp39-abi3-macosx_11_0_arm64.whl (404.4 kB view details)

Uploaded CPython 3.9+macOS 11.0+ ARM64

deepdiff_rs-0.3.1-cp39-abi3-macosx_10_12_x86_64.whl (425.9 kB view details)

Uploaded CPython 3.9+macOS 10.12+ x86-64

File details

Details for the file deepdiff_rs-0.3.1.tar.gz.

File metadata

  • Download URL: deepdiff_rs-0.3.1.tar.gz
  • Upload date:
  • Size: 160.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for deepdiff_rs-0.3.1.tar.gz
Algorithm Hash digest
SHA256 9cc581739823831516c655032aca777a1d1c7d858574ca43d83a08dde40781b2
MD5 8d40f4dbeadc0838be5da94214e96c0f
BLAKE2b-256 f29796a1cec6d6cfe372a93b9d447cade0562f7c75a516f9a904b46661b8b603

See more details on using hashes here.

Provenance

The following attestation bundles were made for deepdiff_rs-0.3.1.tar.gz:

Publisher: publish.yml on ksco92/onix

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file deepdiff_rs-0.3.1-cp39-abi3-win_amd64.whl.

File metadata

  • Download URL: deepdiff_rs-0.3.1-cp39-abi3-win_amd64.whl
  • Upload date:
  • Size: 348.3 kB
  • Tags: CPython 3.9+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for deepdiff_rs-0.3.1-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 58ed14836907c3977b67c4af8d6dac574c5d3fe3145eb92e959326c06dd03c39
MD5 fb0c15134fed8e5dc9a67467e684fb6b
BLAKE2b-256 a479902bad961666719b3d9d98ecaa65c6c4a220839680e434061e501e9c260f

See more details on using hashes here.

Provenance

The following attestation bundles were made for deepdiff_rs-0.3.1-cp39-abi3-win_amd64.whl:

Publisher: publish.yml on ksco92/onix

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file deepdiff_rs-0.3.1-cp39-abi3-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for deepdiff_rs-0.3.1-cp39-abi3-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 044b4c7852d334e29504b1d9333a33124458edcadf51563018cedf4440ce1b28
MD5 d144e6b1a0d76593f39363f4b56cb342
BLAKE2b-256 f4035f1660be6d2415e16867c5fbd677da765cc590f22d03b83096f899f36308

See more details on using hashes here.

Provenance

The following attestation bundles were made for deepdiff_rs-0.3.1-cp39-abi3-manylinux_2_28_x86_64.whl:

Publisher: publish.yml on ksco92/onix

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file deepdiff_rs-0.3.1-cp39-abi3-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for deepdiff_rs-0.3.1-cp39-abi3-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 3b70290beafc72a0d4b98d3054e878628fe0c7d90a3d7a8a06d1055ba5fbc60a
MD5 e1ad02183b54da5518f4877185b5f4e3
BLAKE2b-256 3e561d5627ce9a5d315ad75cccf9c63af656e9f989d561de3a6447f297250fe4

See more details on using hashes here.

Provenance

The following attestation bundles were made for deepdiff_rs-0.3.1-cp39-abi3-manylinux_2_28_aarch64.whl:

Publisher: publish.yml on ksco92/onix

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file deepdiff_rs-0.3.1-cp39-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for deepdiff_rs-0.3.1-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 a2d85b65f674a21cdee4c36fdf4a2ae08dd77b697ecd38dfcbf1b73e02749784
MD5 0ac43714624ddcac4722dbffb756555a
BLAKE2b-256 a20945b4c5d37cacd9ad6838278fb2853b9189f61a7dd9572d550edc119835cb

See more details on using hashes here.

Provenance

The following attestation bundles were made for deepdiff_rs-0.3.1-cp39-abi3-macosx_11_0_arm64.whl:

Publisher: publish.yml on ksco92/onix

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file deepdiff_rs-0.3.1-cp39-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for deepdiff_rs-0.3.1-cp39-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 debececdd8f7256e88ee03ec2f8a291427bd49555fea843b08f9041434421807
MD5 b10804fbcc252ca21fec13f40ee9f0c8
BLAKE2b-256 c5015889c2bf6f4f314fa6c904791b166fecba0d76c072a710fba3ad8ee1be8b

See more details on using hashes here.

Provenance

The following attestation bundles were made for deepdiff_rs-0.3.1-cp39-abi3-macosx_10_12_x86_64.whl:

Publisher: publish.yml on ksco92/onix

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.4.0

6 files

This release

0.3.1 This release

6 files

0.3.0

6 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