Skip to content

perf: build the LoKI workflow once per process - #187

Merged
SimonHeybrock merged 2 commits into
mainfrom
184-loki-workflow-once
Nov 13, 2026
Merged

SimonHeybrock merged 2 commits into
mainfrom
184-loki-workflow-once

Conversation

@SimonHeybrock

Copy link
Copy Markdown
Member

The LoKI bindings built the esssans workflow once per request. LokiAtLarmorWorkflow() takes about 0.7 s of pure-Python time and holds the interpreter lock while it runs; a chain of detector, masks, beam centre, and I(Q) built it four times. The bindings now build it once per process, on first use, and each request works on its own copy (Pipeline.copy(), about 6 ms), so what one request sets does not reach another.

Found by the measurement for step 2 of #184. LoKI tutorial files, 24 cores, before → after:

Wall time Peak memory
chain: detector, masks, beam centre, I(Q) 7.0–7.5 s → 4.0–4.1 s unchanged
4 × I(Q), one workspace thread 15.0–15.3 s → 12.2 s 8 GB, unchanged
4 × I(Q), four workspace threads 19.1–20.7 s → 13.6–14.2 s 26 GB, unchanged
4 × I(Q) through one stage 7.4 s → 6.7–6.8 s 14 GB, unchanged

Masks and beam centre were almost entirely workflow construction: about 1.0 s → 0.15–0.3 s each.

Four workspace threads are still slower than one for plain requests, so the construction was not the only cause. The default number of threads is a separate change.

No test added: the existing tests already run requests with different parameters against the shared workflow and compare I(Q) with plain esssans.

🤖 Generated with Claude Code

LokiAtLarmorWorkflow() takes about 0.7 s of pure-Python time, holding
the interpreter lock, and the LoKI bindings built it once per request
(detector, masks, beam centre, I(Q)). Copying a built workflow takes
about 6 ms. The bindings now build it once, lazily, and give each
request its own copy, so parameters and providers set by one request
do not reach the shared workflow or another request.

Measured on the LoKI tutorial files, 24 cores (wall time, peak memory):

  chain (detector, masks, centre, I(Q)), warm:  7.0-7.5 s -> 4.0-4.1 s
  4 x I(Q), serial:             15.0-15.3 s -> 12.2 s     (8.2-8.4 GB -> 8.0-8.5 GB)
  4 x I(Q), workspace threads:  19.1-20.7 s -> 13.6-14.2 s (~26 GB, unchanged)
  4 x I(Q), one stage:           7.4 s     -> 6.7-6.8 s   (~14 GB, unchanged)

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
The constructor is slow because sciline keeps each generic key as a
node of a networkx graph and rebuilds the graph at each assignment.
sciline plans to handle generics differently, so the comment says to
measure again then.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
@SimonHeybrock
SimonHeybrock merged commit 5f006e8 into main Nov 13, 2026
2 checks passed
@SimonHeybrock
SimonHeybrock deleted the 184-loki-workflow-once branch November 13, 2026 06:04
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