Skip to content

perf!: share Python identity work per discovery pass and keep compile phases out of sinks - #1501

Merged
chio-labs-delivery[bot] merged 20 commits into
mainfrom
perf/python-identity-sharing
Nov 15, 2026
Merged

chio-labs-delivery[bot] merged 20 commits into
mainfrom
perf/python-identity-sharing

Conversation

@kvlonge

@kvlonge kvlonge commented Nov 15, 2026 •

Copy link
Copy Markdown
Contributor

Why

Discovery re-read, re-parsed and re-hashed shared helpers per Python node. sqb dev discovered twice on start, and sinks slowed sqb compile by receiving every phase event. The dense delta loop failed on runner wall-time noise.

Changes

  • One identity pass per discovery memoises each object's source, hash, called names, module and path parts. Fingerprints are byte-identical.
  • Python 3.12 parses class starts once per file.
  • sqb debug reads configuration (with its checks) and providers only, so sqb dev's connection check no longer discovers twice.
  • Breaking: sqb compile no longer sends phase operation events to project lifecycle sinks. Invocation events still do.
  • The dense delta loop gates on analysed-model counts and same-job CPU ratio, not wall time.
  • object_source.py and identity_pass.py stay Python (they read live user functions), as approved.
  • Called names resolve through the function's own globals, not sys.modules, which may hold an unrelated python package after discovery.

Verification

  • Counting test, 500 nodes sharing helpers: each file read, parsed and hashed at most once (main: 3,000 parses; now 6). Fails with a per-node memo.
  • Golden fingerprints from main match.
  • sqb dev imports project Python once on start (was twice). Compile sinks get invocation events only. sqb debug still rejects a forbidden local SQL analysis opt-out. An unrelated python package no longer hides helpers (fails without the fix).
  • Evidence only (same machine, 3 alternating runs, medians, load 1.1–2.0, 8 cores), 500 nodes: discover 5.7 s → 1.3 s, wall 5.96 → 1.58 s, CPU 5.54 → 1.47 s. A 50 ms/event sink adds 0.30 s to a 100-node compile on 0.230.1; 0.08 s now.
  • Delta loop, 3,000 models: passes (CPU ratios 0.24–0.29); with deltas disabled it fails the CPU gate (0.997). Delta CPU matches 0.230.1 (1.78 vs 1.75 s).
  • make check-ci passes.

DuckShop: adds edge_cases/orchestration/python_identity_class_shapes.py.

- Compile: a sensor or calendar declared inside a `_`-prefixed folder under
  orchestration/sensors/ or orchestration/calendars/ now fails with an error
  naming the file, since such folders are private support.
- SQBRPYTHON016-020: module paths, private support, module surface, import
  direction and no docstring on sensor and calendar functions.
- Provider and orchestration rules share parsing and import resolution.
- Evict nested namespace packages before their parents between projects in one
  interpreter, so a project importing orchestration.* no longer breaks the
  next compile.
- Docs and DuckShop fixtures for each rule.
A provider whose required secret settings are unset no longer stops
every command. Static commands (compile, dag, format, scope, lineage,
rules run) still fail with D012 naming the variable, unless
--allow-missing-secrets, SQLBUILD_ALLOW_MISSING_SECRETS or the local
allow_missing_secrets setting allows it. The project file rejects that
setting.

build, load and check read secrets only for the providers the selected
nodes and sinks use, and fail before anything runs when one is missing.
Providers are instantiated lazily in the runtime session.

sqb debug reports how many providers are ready and lists missing
secrets (--verbose lists every one). Location health reports
missing_secrets and exits 1, and the Providers page marks unset
secret settings.
…PYTHON rules

sqb test now runs the project's pytest modules under tests/python/ and
tests/providers/ after its SQL tests, from the project directory with
--import-mode=importlib. --sql and --python pick one kind. Selecting a
Python node runs the tests in its mirrored folder; selecting only models
or unit tests runs none. The command fails when either kind fails, and
fails early when Python tests exist but pytest is not installed. sqb test
--since, --inspect, review and ad-hoc runs stay SQL-only, and sqb build
never runs Python tests. With --json, pytest writes to stderr.

- SQBRPYTHON021: a test sits in the folder mirroring the code it tests,
  and test_<name>.py has a <name>.py or <name>/ beside that code.
- SQBRPYTHON701-724: the Fensu test-shape rules (table-driven dataclass
  cases, naming, parametrize ids), applied only to Python tests.
- Docs for sqb test, sqb build, testing, project layout, custom rule
  tests and the Python Rules reference, plus DuckShop fixtures.
sqb compile imports project Python with no warehouse connection, so the
code that runs then must not reach outside the machine. SQBRPYTHON022
checks calls at module scope, in class bodies and directly in @factory
bodies, follows the project functions they call through their imports,
and reports a call that reaches a subprocess, an HTTP request, a socket,
a database or warehouse driver, or a cloud or SSH client. It reads
source only and follows only calls it can resolve, so a call through a
variable or an object is never reported.

- approved_loader_boundaries lists exact project functions the walk does
  not enter; a glob fails configuration and a module name fails the run.
- Findings are reported at the root call and name the external call and
  where it is. Results per function are memoized, with a scaling test
  over deep shared call chains.
- Docs for the rule, its option and its reference row, and a DuckShop
  violation behind a branch compile never takes.
…sharing

# Conflicts:
#	crates/sqlbuild-python/src/bindings/_helpers/debug_command/run_debug.rs
…globals

An identity built after discovery looked up the node's module through
sys.modules. When discovery had put back an unrelated top-level python
package, that lookup found the unrelated module, so helpers were no longer
dependencies and editing one did not change the node's version hash.
@chio-labs-delivery
chio-labs-delivery Bot added this pull request to the merge queue Nov 15, 2026
…the identity pass

The shared Python identity pass and its native hooks add 169 runtime and 51
crate code lines over the caps measured before this change.
@kvlonge
kvlonge removed this pull request from the merge queue due to a manual request Nov 15, 2026
@chio-labs-delivery
chio-labs-delivery Bot added this pull request to the merge queue Nov 15, 2026
Merged via the queue into main with commit d15ee25 Nov 15, 2026
34 checks passed
@chio-labs-delivery
chio-labs-delivery Bot deleted the perf/python-identity-sharing branch November 15, 2026 16:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant