Photon Fallback Analyzer — zero-touch Databricks cost forensics (.pth self-arm + bundled JVM listener)
Project description
clusop — Photon Fallback Analyzer
pip install clusop
clusop finds the money Databricks Photon quietly burns. When Photon hits an operator it can't run (a Python UDF, a struct-IN filter, an unsupported Delta feature), it silently falls back to the JVM — you keep paying the 2–2.9× Photon DBU premium while getting JVM speed. clusop detects those fallbacks from the executed plan, estimates the wasted spend, and proposes a fix. It never touches your job.
One install, two halves, zero config
A single pip install clusop ships both halves and arms itself:
- a Python
.pth(clusop_autoload.pth) that Python'ssitemachinery runs at interpreter startup → importsclusop.runtime.bootstrap→ arms automatically. You do notimport clusopanywhere in your job. - a bundled Scala JAR (
clusop/jars/photon_listener.jar) — the actualQueryExecutionListener. The bootstrapaddJars it and registers it over Py4J.
Install it as a cluster/job library (production path) so every interpreter that
starts already has it. %pip install clusop + dbutils.library.restartPython() works for
dev.
Everything is auto-detected at runtime — cloud (from the instance type), DBR (from
DATABRICKS_RUNTIME_VERSION), cluster shape, and whether the JVM is reachable. No
per-user setup; a new customer pip-installs and it works.
What it costs you: nothing if it can't run safely
- Fail-open everywhere. Any error in arming, listening, parsing, or dispatch is swallowed. clusop never breaks, slows, or blocks a customer query.
- Needs a SINGLE_USER / dedicated cluster for the JVM listener. On USER_ISOLATION (Shared) clusters the JVM is sealed behind Spark Connect — clusop detects this and stays dormant rather than failing.
- Propose-never-apply. clusop emits a signal and a Teams card. A human decides.
How a signal is born
- The JVM listener sees a finished query and reads its executed plan.
- The structural parser (src/clusop/analysis/parser.py,
mirrored in Scala) decides if this is a real fallback. The hard part: a clean Photon
query always ends in one terminal
ColumnarToRow(the normal result boundary) — that is not a fallback. Real fallback is mid-planColumnarToRow,RowToColumnarround-trips, orBatchEvalPython/ArrowEvalPython. Counting raw occurrences false-positives; clusop doesn't. - The waste model (waste.py) sizes the loss:
runtime × Σ(node DBU/hr) × $rate × (photon_premium−1) × fallback_weight. - Confidence (confidence.py) is decomposed into four legs — parse / diagnosis / cost / recommendation. A fix (rewrite the UDF) needs only parse+diagnosis; a disable-Photon recommendation is a dollar decision and is capped by the cost leg.
- The signal flows to a driver batcher (dedup by signature) → central aggregator (idempotent upsert, suppression, prioritization) → Teams card.
Cost: modeled now, billed if granted
clusop always works with a modeled cost (public price table → MEDIUM cost confidence).
If the workspace can read system.billing.usage, the
CostTierResolver reconciles the estimate to billed
dollars (HIGH confidence). Detection never depends on system tables — they only upgrade
the cost layer. Prices are reference data, not something clusop invents per-row.
Certifying it's real
harness/certify.py runs on a dedicated cluster, captures real executed plans for known clean / known-fallback fixtures, and reports catch-rate plus a DBR-stamped Delta feature-support matrix — derived, never hand-maintained.
Layout
src/clusop/
runtime/ bootstrap (arming), detect (cloud/DBR/shape/jvm)
analysis/ parser · waste · confidence · signal
pricing/ price_table.json · provider
service/ aggregator · resolver · suppression · teams · onboard
jars/ photon_listener.jar (baked in by the release workflow)
scala/ the QueryExecutionListener (sbt; mirror of the Python parser)
harness/ certify.py (catch-rate + Delta matrix, run on a dedicated cluster)
tests/ parser / waste / confidence
See SPEC.md for the full design and invariants.
Release
Push-button: the Publish workflow auto-versions
(max(PyPI, tags)+1), builds the JAR with sbt, bakes it into the wheel, lints+tests,
gates on (.pth at wheel root AND JAR bundled), then publishes via PyPI Trusted
Publishing (OIDC — no stored token) and tags the bump.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file clusop-0.0.17.tar.gz.
File metadata
- Download URL: clusop-0.0.17.tar.gz
- Upload date:
- Size: 103.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
612a0dd7717fc20a5145d92482ace7f8562f2a68e68cf269113866d2287832b2
|
|
| MD5 |
96134fb2eb173473b251ffdf656738a5
|
|
| BLAKE2b-256 |
c969c6ce4f69d2a99792b47f54d8d66a8ebfdfa8b3b9761d20e26e8637870c96
|
Provenance
The following attestation bundles were made for clusop-0.0.17.tar.gz:
Publisher:
release-pypi.yml on yogasathyandrun/implementation-db
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
clusop-0.0.17.tar.gz -
Subject digest:
612a0dd7717fc20a5145d92482ace7f8562f2a68e68cf269113866d2287832b2 - Sigstore transparency entry: 1885278744
- Sigstore integration time:
-
Permalink:
yogasathyandrun/implementation-db@6aa386e751b1241dc2a560c51820ce58b4598dc5 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/yogasathyandrun
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-pypi.yml@6aa386e751b1241dc2a560c51820ce58b4598dc5 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file clusop-0.0.17-py3-none-any.whl.
File metadata
- Download URL: clusop-0.0.17-py3-none-any.whl
- Upload date:
- Size: 98.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bc479855e9cfd77765de026f2c042c96b3b8efcebcd82afdda11d3e150bed74a
|
|
| MD5 |
4000ca4661562c1537d1f3b2dcca08f7
|
|
| BLAKE2b-256 |
499f46b5663fa62776c9b9302203e74afb17e596ef9b4d49cf40169cd45d222e
|
Provenance
The following attestation bundles were made for clusop-0.0.17-py3-none-any.whl:
Publisher:
release-pypi.yml on yogasathyandrun/implementation-db
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
clusop-0.0.17-py3-none-any.whl -
Subject digest:
bc479855e9cfd77765de026f2c042c96b3b8efcebcd82afdda11d3e150bed74a - Sigstore transparency entry: 1885278810
- Sigstore integration time:
-
Permalink:
yogasathyandrun/implementation-db@6aa386e751b1241dc2a560c51820ce58b4598dc5 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/yogasathyandrun
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-pypi.yml@6aa386e751b1241dc2a560c51820ce58b4598dc5 -
Trigger Event:
workflow_dispatch
-
Statement type: