Evaluate whether a Rust implementation of scan(text, engine="regex") should replace DataFog's existing fast-install Python core.
PII fields: EMAIL, PHONE, SSN, CREDIT_CARD, IP_ADDRESS, DATE, and ZIP_CODE.
Exclude spaCy, GLiNER, smart, and all NER model download/loading time.
- Repository:
datafog/datafog-python - Version:
4.8.0a6 - Commit:
75e414b2 - Invocation:
scan(text, engine="regex") - Fields:
EMAIL,PHONE,SSN,CREDIT_CARD,IP_ADDRESS,DATE,ZIP_CODE
- Precision, recall, and F1 overall and by PII field
- Output-difference rate: Rust
scanvs pinned Python baseline - Total runtime, p50/p95 latency, and sentences/second
- Startup time
- Peak memory use
The existing datafog package remains the Python baseline. The parallel Rust-backed binding is distributed as datafog-core-python and imported as datafog_core.
python3 -m pip install maturin
maturin build --manifest-path bindings/python/Cargo.toml --release
python3 -m venv .venv
.venv/bin/python -m pip install target/wheels/*.whl
.venv/bin/python -c 'from datafog_core import scan; print(scan("Email jane@example.com"))'Run its installed-wheel fixture test with:
.venv/bin/python bindings/python/tests/test_installed.pyThe browser package is @datafog/wasm. Build it with the Rust WASM target and a matching wasm-bindgen CLI:
rustup target add wasm32-unknown-unknown
cargo install wasm-bindgen-cli --version 0.2.127 --locked
npm ci --prefix bindings/wasm
npm run build --prefix bindings/wasmUse it from a browser ESM application:
import { init, scan } from "@datafog/wasm";
await init();
console.log(scan("Email jane@example.com"));Run the installed-package browser test with:
npx --prefix bindings/wasm playwright install chromium
npm run test:package --prefix bindings/wasmUse this workflow to compare the pinned datafog-python baseline, the Rust core, and the Rust-backed Python binding on another Mac. It works on Apple Silicon and Intel Macs; the generated wheel filename differs by Python version and CPU architecture.
- Git
- Python 3.10 or newer (
python3 --version) - A stable Rust toolchain (
rustc --version); install it with rustup if needed - Network access: the comparison script installs the pinned Python baseline from GitHub into a temporary virtual environment
git clone https://github.com/DataFog/rust-poc.git
cd rust-poc
python3 -m venv .venv
.venv/bin/python -m pip install --upgrade pip maturin
.venv/bin/maturin build --manifest-path bindings/python/Cargo.toml --releaseRun the final-fixture comparison across all three implementations:
WHEEL="$(find target/wheels -name 'datafog_core_python-*.whl' -print -quit)" \
&& .venv/bin/python scripts/compare.py fixtures/final.jsonl --wheel "$WHEEL"Run the scaling comparison across the development and final fixtures:
WHEEL="$(find target/wheels -name 'datafog_core_python-*.whl' -print -quit)" \
&& .venv/bin/python scripts/compare.py scale fixtures/development.jsonl fixtures/final.jsonl --wheel "$WHEEL"Each command builds the release Rust runner, creates isolated temporary environments for the Python baseline and binding, and writes a timestamped JSON report to results/.
- Run a comparison:
python3 scripts/compare.py fixtures/final.jsonl. - Include the Python binding wheel:
WHEEL="$(find target/wheels -name 'datafog_core_python-*.whl' -print -quit)" && python3 scripts/compare.py fixtures/final.jsonl --wheel "$WHEEL". - Or run batch scaling:
python3 scripts/compare.py scale fixtures/development.jsonl fixtures/final.jsonl. - Open
results-viewer.htmlin a browser and select the timestamped JSON report fromresults/.
- Open
data-doctor.htmlin a browser and select a fixture JSONL file. - Review one sentence at a time; mark it correct, flag it, or add/change/remove labels.
- Download the updated fixture, inspect its Git diff, then replace the source fixture intentionally.
Data Doctor expects one JSON object per line. Each record requires id, text, and entities; category is optional.
{"id":"case-001","text":"Email jane@example.com","entities":[{"label":"EMAIL","text":"jane@example.com","start":6,"end":22}]}Each entity uses a supported label, the exact matched text, and zero-based Unicode code-point offsets with an exclusive end.
- 100 sentences for development/regression
- Frozen 1,000 sentences for final evaluation
- Production migration or other code changes

