polars-rt
A Rust extension for Polars that pre-compiles a lazy query plan once, then re-executes it at low latency by injecting new DataFrames at runtime — without re-running the optimizer.
Status: experimental workaround for pola-rs/polars#25246. Currently tested on polars 1.38.1 only. The implementation relies on internal Polars APIs that may change without notice. Use with that in mind.
The problem
Every call to LazyFrame.collect() runs the Polars optimizer from scratch. For a fixed expression (e.g. a decision tree or scoring function) applied to a stream of small batches, this optimization cost dominates execution time and grows super-linearly with plan complexity.
How it works
There are two execution modes with different trade-offs.
RealtimeLazyFrame — optimize once, re-compile physical plan each call
Runs the Polars optimizer once at construction and stores the resulting IR arena. Each collect() clones the arena, replaces placeholder scan nodes with IR::DataFrameScan nodes containing the supplied DataFrames, then calls create_physical_plan and executes. The optimizer is eliminated; the per-call cost is physical plan compilation plus execution.
CompiledRealtimeLazyFrame — compile once, inject via slots
Produced by calling .compile() on a RealtimeLazyFrame. Runs create_physical_plan once and keeps the resulting executor tree alive between calls. Each collect() drops DataFrames directly into pre-wired Arc<Mutex<Option<DataFrame>>> slots that the placeholder executors hold references to — no plan recompilation, no arena clone. This is the fast path for high-frequency hot loops.
Caution: this path is only safe for a subset of queries. Polars physical executors are &mut self and several carry internal state that is consumed on first execution; re-running them on a second collect() call will panic or silently return wrong results. Use RealtimeLazyFrame (which rebuilds the physical plan on every call) if your query contains any of the following:
| Polars operation | Why it breaks on re-execution |
|---|---|
pl.concat / pl.DataFrame.vstack |
Union streaming executor uses one-shot channels that are drained on first run |
lf.join(..., how="cross") |
CrossJoin executor materialises the right side once and does not reset |
lf.join(..., how="asof") |
Stateful sort/merge step is not idempotent |
Aggregations with maintain_order=True |
Sort state may not reset between calls |
scan_parquet / scan_csv / scan_ipc mixed into the plan |
Real file scans use streaming file iterators; cursor is not rewound |
Operations that are safe to compile include: select, with_columns, filter, group_by (without maintain_order), sort, rename, drop, explode, unnest, join (inner/left/right between two placeholders or a placeholder and a literal in-memory frame), struct expressions, and when/then/otherwise chains. In practice .compile() works well for pure expression evaluation and scoring pipelines over placeholder inputs.
import polars as pl
from rtlf import PyRealtimeLazyFrame
schema = pl.Schema({"feat_0": pl.Int32, "feat_1": pl.Int32})
expr = pl.when(pl.col("feat_0") < 5).then(pl.lit(1)).otherwise(pl.lit(0))
placeholder = PyRealtimeLazyFrame.read_placeholder("input", schema)
rtlf = PyRealtimeLazyFrame(placeholder.select(expr))
# Option A: re-compiles physical plan each call
for batch in stream:
result = rtlf.collect({"input": batch})
# Option B: compile once, inject via slots (maximum speedup)
compiled = rtlf.compile()
for batch in stream:
result = compiled.collect({"input": batch})
Benchmarks
All benchmarks use batch size=1000 rows, 10 timed runs per depth point. Results show mean time and speedup relative to LazyFrame.collect().
Linear chain
A chain of stacked pl.when(...).then(...).otherwise(...) calls — depth is the number of nodes. This is the typical structure of a scoring function or feature pipeline.
depth_range lf_ms rtlf_ms compiled_ms rtlf_speedup compiled_speedup
-------------------------------------------------------------------------------
1–9 1.24 1.25 0.95 0.99x 1.31x
10–99 12.93 9.57 5.78 1.35x 2.24x
100–999 502.97 216.92 21.52 2.32x 23.37x
1000 1545.78 670.64 38.64 2.30x 40.00x
At 100+ nodes, CompiledRealtimeLazyFrame is 23–40x faster than plain LazyFrame. The optimizer cost grows super-linearly with plan depth; rtlf eliminates it entirely. Even the uncompiled rtlf gives 2.3x at scale. Note that 100+ node chains are uncommon in practice — for typical queries the gain is more modest.
Decision tree
Width-5 branching tree (each depth level fans out 5 ways), so node count is exponential in depth.
depth lf ms rtlf ms compiled ms rtlf speedup compiled speedup
------------------------------------------------------------------------
1 1.419 1.413 0.946 1.00x 1.50x
2 5.797 5.276 4.392 1.10x 1.32x
3 20.482 15.234 10.153 1.34x 2.02x
4 80.748 36.744 11.262 2.20x 7.17x
5 386.197 109.837 11.886 3.52x 32.49x
6 2651.983 643.382 48.658 4.12x 54.50x
Even at shallow depth the exponential node count makes optimizer overhead dominate. By depth 6, CompiledRealtimeLazyFrame is 54x faster than plain LazyFrame. These numbers reflect a fairly extreme plan size — real-world decision trees are typically shallower and the speedup will be lower.
Scaling results
Running the benchmarks
uv sync
uv run maturin develop --release
source .venv/bin/activate
python benchmark.py
# outputs: benchmark.png, benchmark_linear.parquet, benchmark_tree.parquet
Building
Requires:
- Rust nightly (
nightly-2026-01-09) — set viarustup override set nightly-2026-01-09inrtlf/ - Python ≥ 3.12,
uv
cd rtlf
uv sync
uv run maturin develop --release
Implementation notes
Placeholder mechanism (src/realtime.rs)
There is no clean public API in create_physical_plan for injecting custom data sources, so placeholders are disguised as real Parquet scans. read_placeholder() constructs a DslPlan::Scan with two sentinel path tokens: _rtlf::placeholder (the marker) and the placeholder name. The optimizer treats this as an ordinary file scan and optimizes around it normally.
At construction time, RealtimeLazyFrame::new() runs the optimizer and walks the resulting IR arena to record the node index of each placeholder scan. On collect(), these nodes are patched to IR::DataFrameScan in a cloned arena before create_physical_plan is called.
Compiled slot injection (src/compiled.rs, src/executor.rs)
CompiledRealtimeLazyFrame reuses the same physical executor tree across calls. The key problem is how to get fresh DataFrames into an already-compiled tree without rebuilding it.
The approach uses StreamingExecutorBuilder — a function-pointer hook that create_physical_plan calls when it encounters a scan node. By passing placeholder_builder as this hook, the compiled path intercepts placeholder scans during the single up-front compilation, replacing each one with a PlaceholderExec that holds a Slot (Arc<Mutex<Option<DataFrame>>>). The slot references are also stored in CompiledRealtimeLazyFrame. On each collect(), DataFrames are moved into the slots then the executor runs — no arena clone, no plan recompilation.
An earlier approach routed DataFrames through the ExecutionState cache (the standard Polars mechanism for pre-computed frames). This worked but was measurably slower than the slot approach because the cache involves additional indirection and allocation on the hot path.
Caveats
This library is experimental and works well for a limited set of use cases. Known constraints:
- The
StreamingExecutorBuilderhook is only called for scan nodes, so queries that involve non-placeholder file scans (e.g. a join against a real Parquet file) go through the normal path and are handled byRealtimeLazyFramerather than the compiled path. - The placeholder detection relies on a specific path format inside
IR::Scan. Any internal polars refactor that changes how scan sources are stored could break it. - Concurrent
collect()calls on a singleCompiledRealtimeLazyFrameare serialised by a mutex on the physical executor. The executor tree cannot be cloned (polarsExecutordoes not implementClone), so true parallelism requires oneCompiledRealtimeLazyFrameper thread — call.compile()once per thread at startup. Depending on thread count and plan complexity, this may actually be faster than sharing a single instance with lock contention.
Source files
src/realtime.rs—RealtimeLazyFrame: optimizer-once, re-compile-physical-plan-each-call pathsrc/compiled.rs—CompiledRealtimeLazyFrame: compile-once, slot-injection pathsrc/executor.rs—PlaceholderExec,Slottype,placeholder_builderhook, placeholder node detectionsrc/python/— pyo3 wrappers; GIL released viapy.detach()duringcollect()src/error.rs—PolarsError→ Python exception mapping (orphan rule workaround)
Version pinning
DSL_SCHEMA_HASH is a SHA256 of the Polars plan type definitions baked into the compiled .so at build time. It must match exactly between the extension and the installed Python polars wheel. Crates.io published versions do not correspond to any Python release tag, so all polars crates are patched via [patch.crates-io] to the py-1.38.1 git tag of the polars monorepo. Building against any other source will produce a hash mismatch at runtime.
Metadata
Release files for rtlf 0.41.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distributions (wheels)
Total release size: 377.3 MB
Release files / rtlf-0.41.2-cp314-cp314-win_amd64.whl
| Download URL | rtlf-0.41.2-cp314-cp314-win_amd64.whl |
|---|---|
| Size | 34.6 MB |
| Tags | CPython 3.14 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
195e2d66c371086556d521413d554ce770788934ede244c35c522aa7d4c1f117
|
|
BLAKE2b-256 checksum How to use checksums |
ea8d6c530d4c446210b01278d20e7f9666e4fac638411e5de94f1cce1b81976a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 Jun 6, 2026.
Transparency logRelease files / rtlf-0.41.2-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | rtlf-0.41.2-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 35.7 MB |
| Tags | CPython 3.14 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
700042fef41664fddf0682b28f536a62a660d137d50276c28b82b225bbc64296
|
|
BLAKE2b-256 checksum How to use checksums |
e1b695a307fe551123617b1185b1bfbb45cde4e5016ed6f24d298c762317d6b1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 Jun 6, 2026.
Transparency logRelease files / rtlf-0.41.2-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | rtlf-0.41.2-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 26.1 MB |
| Tags | CPython 3.14 Linux glibc 2.17+ ARM64 |
|
SHA-256 checksum How to use checksums |
a2a713a0ed7e18d13900ef86aa9fbbfc4335ba866311d6a4435539f921bcec99
|
|
BLAKE2b-256 checksum How to use checksums |
d700c0cf94e0ee6df62333b054910976d26c8a824e346f9d169efc9adbf08be1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 Jun 6, 2026.
Transparency logRelease files / rtlf-0.41.2-cp314-cp314-macosx_11_0_arm64.whl
| Download URL | rtlf-0.41.2-cp314-cp314-macosx_11_0_arm64.whl |
|---|---|
| Size | 29.4 MB |
| Tags | CPython 3.14 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
f4b825c30b3c5fa5215694e09c231fb82aea601d44b33afc0fb03cf7b900766f
|
|
BLAKE2b-256 checksum How to use checksums |
27a49764c81962dc0b14c40ef814196cf84efd17693923aac1c5859a9221f27f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 Jun 6, 2026.
Transparency logRelease files / rtlf-0.41.2-cp313-cp313-win_amd64.whl
| Download URL | rtlf-0.41.2-cp313-cp313-win_amd64.whl |
|---|---|
| Size | 34.6 MB |
| Tags | CPython 3.13 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
e1c89f587dec0134b2346dff355e00e809bb439ebb7aeaa4f48c173970b2060e
|
|
BLAKE2b-256 checksum How to use checksums |
4d3c57a44a56ce76f5ea1977c0988195f0bd213fe3609da095e1ebb0a3e29269
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 Jun 6, 2026.
Transparency logRelease files / rtlf-0.41.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | rtlf-0.41.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 35.7 MB |
| Tags | CPython 3.13 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
d86a553a2a6c062397d91b24adcc9e1556f5dfdd3ae85420182a55ad99e8086c
|
|
BLAKE2b-256 checksum How to use checksums |
73443827b8ad8981da5d5c935a35409cf53fd47fd89f0fcead0f5458baa32595
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 Jun 6, 2026.
Transparency logRelease files / rtlf-0.41.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | rtlf-0.41.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 26.1 MB |
| Tags | CPython 3.13 Linux glibc 2.17+ ARM64 |
|
SHA-256 checksum How to use checksums |
7a4e271d705e887b3daa4a4260af7ee12a9847fb14334553d985a21a5958f82e
|
|
BLAKE2b-256 checksum How to use checksums |
1e8beadc7907c56baa3945574749c0872f5562e63e707e127fa5d98dc391cff4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 Jun 6, 2026.
Transparency logRelease files / rtlf-0.41.2-cp313-cp313-macosx_11_0_arm64.whl
| Download URL | rtlf-0.41.2-cp313-cp313-macosx_11_0_arm64.whl |
|---|---|
| Size | 29.4 MB |
| Tags | CPython 3.13 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
f6d44558b1f8092e818dbc7b4c123054d317509d4e30e4f0bcfbfeed7d905152
|
|
BLAKE2b-256 checksum How to use checksums |
fd7ba81fc2e60edcce3d3c264e513f9c1188af40c8fe0a21ee046646143bfca3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 Jun 6, 2026.
Transparency logRelease files / rtlf-0.41.2-cp312-cp312-win_amd64.whl
| Download URL | rtlf-0.41.2-cp312-cp312-win_amd64.whl |
|---|---|
| Size | 34.6 MB |
| Tags | CPython 3.12 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
9b2864ff165cec5262e396dd7d720865d12d11ec8a3f4b18ef04d4f6bc2d26d0
|
|
BLAKE2b-256 checksum How to use checksums |
d1b59a48696a2ab6a2ac6249e96b2047002f87cae25f0ded325b4ec15b6ff43a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 Jun 6, 2026.
Transparency logRelease files / rtlf-0.41.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | rtlf-0.41.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 35.7 MB |
| Tags | CPython 3.12 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
629978268bd63626275a47cd1755ba9cb71c5cf23b4168822188d7b7860d9b4c
|
|
BLAKE2b-256 checksum How to use checksums |
59f6bdcf1d7ab96e56f9f6a628b2b629258ceea3cbd8317cb08ed0fa940cb156
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 Jun 6, 2026.
Transparency logRelease files / rtlf-0.41.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | rtlf-0.41.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 26.1 MB |
| Tags | CPython 3.12 Linux glibc 2.17+ ARM64 |
|
SHA-256 checksum How to use checksums |
e71f4fe94fbf48f8f3f7cfed302937c14cad63ef1ed611caa9dc0b1d7c8e6a27
|
|
BLAKE2b-256 checksum How to use checksums |
4b38647d738acd72d11a9d98603d9c5ba3cc45963cedf3449906e75e906cc860
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 Jun 6, 2026.
Transparency logRelease files / rtlf-0.41.2-cp312-cp312-macosx_11_0_arm64.whl
| Download URL | rtlf-0.41.2-cp312-cp312-macosx_11_0_arm64.whl |
|---|---|
| Size | 29.4 MB |
| Tags | CPython 3.12 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
78e6612b00de15e900b8e154ce4d4be986ad9a871ed704815253f884d9e87f11
|
|
BLAKE2b-256 checksum How to use checksums |
38cc90fe4f0de2470c7203f19d5e171cc55d5697734c95fc5b009d41ab1be0b7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 Jun 6, 2026.
Transparency logSecurity for rtlf 0.41.2
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.
Full provenance
All 12 files in this release have been uploaded with provenance metadata.
Attestation for rtlf-0.41.2-cp314-cp314-win_amd64.whl
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 Jun 6, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.