Skip to content

perf(engine): an update that gives a linear constraint's coefficients new numbers at the coordinates they had skips most of the build - #2071

Draft
FBumann wants to merge 11 commits into
perf/update-numbers-onlyfrom
perf/update-coefficients
Draft

FBumann wants to merge 11 commits into
perf/update-numbers-onlyfrom
perf/update-coefficients

Conversation

@FBumann

@FBumann FBumann commented Oct 28, 2026 •

Copy link
Copy Markdown
Collaborator

Prompt: Do the coefficient one first

Note

The following content was generated by AI.

An update that changes a linear constraint's coefficients, at the coordinates they had, now keeps the labels and re-reads only the matrix entries of the constraints it feeds. On top of #2070, such an update takes 0.25–0.49× the time. The solver still loads again.

What changed

#2070 counted a parameter that scales a variable as structural, so any such update built in full. Over the ports, those were 67 of the 87 single-parameter updates that missed #2070's path.

The held solver is untouched. A changed coefficient fails its keeps() test, so the next solve loads the model again. Taking changed coefficients in place (HiGHS changeCoeff, Gurobi chgCoeffs) is the next PR.

Docs: docs/howto/faster.md and the labels paragraph of docs/development/architecture.md name coefficients and say the solver still loads again.

Probes and reach

tests/test_update.py:

Outside the suite: storage xs eta and network s eta take the path, and their hand-off and diagnostics equal a fresh build's.

Mutation table

Each guard broken by one text substitution, the full suite run (pytest -q -n 4), the file restored with git checkout --, __pycache__ dropped on both sides, the tree clean after each. The first six at 6db4b14, the last three at 8b6ac48.

mutation result
coefficients never read again caught, 37 failed
a quadratic constraint's coefficients not structural caught, 1 failed
a factor of a product not a coefficient caught, 36 failed
a divisor not a coefficient caught, 4 failed
rows placed densely under a where caught, 5 failed
the rows after a splice not moved caught, 9 failed
the coefficient range not read again still green at 6db4b14; caught, 26 failed, by the diagnostics comparison added for it
the nonzero count not read again still green at 6db4b14; caught, 11 failed, the same way
coefficient ranges left where a refill put them caught, 16 failed

The diagnostics comparison also found that #2070 listed a re-read bound or right-hand-side range at the end of its frame. That is fixed on #2070 (c70193d) and merged here.

A/B of the update, this container (4 cores, not the publishing machine)

Base #2070's head c70193d, head 8b6ac48. One fresh process per measurement, base and head alternated ABBA for three rounds. Each process builds once, then times 12 calls of model.update({param: …}), each with the values ×0.9–1.1 at the same coordinates, and reports the median; the table gives the median over the three processes. Only the update is timed: no solve, so the solver's reload is not in these numbers. Started once the load average fell below 1.5: 1.36 before, 1.31 after.

model, what changes base ms head ms head ÷ base head faster in
storage xs (10k columns), eta 36.4 17.9 0.49 3/3
storage s (100k columns), eta 52.2 25.6 0.49 3/3
network s (100k columns), eta 104.8 37.6 0.36 3/3
network m (1M columns), eta 352.4 86.9 0.25 3/3
storage xs, load, control: on #2070's path either way 11.2 11.1 0.99 2/3

Per-process medians, ms: storage xs eta base 39.5 / 35.3 / 36.4, head 18.5 / 17.9 / 16.2; storage s base 47.2 / 55.1 / 52.2, head 21.6 / 25.9 / 25.6; network s base 104.8 / 113.9 / 98.2, head 37.6 / 35.1 / 38.4; network m base 372.0 / 352.4 / 336.3, head 85.0 / 93.4 / 86.9; control base 9.8 / 11.3 / 11.2, head 11.1 / 11.1 / 11.0.

Gates at 8b6ac48, on mathspec 0.4.0

No pixi in this container, so each gate ran in a uv environment synced from #2065's uv.lock (--group dev --group docs --all-extras, Python 3.12, polars 2.0.0):

  • ruff check ., ruff format --check . (0.16.9): clean.
  • pyrefly check on the package (1.3.1): 0 errors.
  • pytest -q -n 4: 5945 passed, 459 skipped, 4 xfailed.
  • pytest tests/test_docs_math.py tests/test_docstring_links.py (docs-test): 116 passed at 6db4b14.

Not run: docs-build, the floors environment, test-via-pyarrow.

Not done. The solver still loads again on a changed coefficient, which is the next PR. Two smaller cases still build in full: a where whose answer does not change (11 port updates) and a constraint that dropped a row (9). Stacked on #2070.

🤖 Generated with Claude Code

https://claude.ai/code/session_018B3nA4oeSor7jjZ4vwux1G

… new numbers at the coordinates they had skips most of the build

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018B3nA4oeSor7jjZ4vwux1G
…erf/update-coefficients

# Conflicts:
#	src/specsolve/_engine/assembly.py
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018B3nA4oeSor7jjZ4vwux1G
@coderabbitai

coderabbitai Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 609a764e-3faa-48b7-a94a-72fe2eddafad

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

@read-the-docs-community

read-the-docs-community Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

@codspeed

codspeed Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Merging this PR will regress 1 benchmark

1 warning, 1 note

⚠️ 6 benchmarks with a significant change ran on different hardware

Their base and head results were measured on machines with a different CPU, core count or memory, so the changes might not come from the code. Run base and head on the same runner type.

Learn more about Macro Runners

See affected benchmarks

ℹ️ 104 benchmarks have no flamegraph

The flamegraph wasn't generated: the symbols of the profiling trace could not be resolved, because no information about the language frames was collected.

See affected benchmarks

⚡ 5 improved benchmarks
❌ 1 regressed benchmark
✅ 98 untouched benchmarks
⏩ 307 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
❌ test_read[commitment-s-specsolve-parquet] 220.7 KB 685.8 KB -67.82%
⚡ test_window[sector-s-specsolve-highs-coefficient] 7.8 MB 5.4 MB +43.66%
⚡ test_window[network-s-specsolve-highs-coefficient] 19.7 MB 15.2 MB +30.08%
⚡ test_window[commitment-s-specsolve-highs-coefficient] 2 MB 1.6 MB +27.33%
⚡ test_window[storage-s-specsolve-highs-coefficient] 16.1 MB 12.8 MB +25.69%
⚡ test_window[commitment-s-specsolve-highs-one] 1,158.4 KB 939.5 KB +23.3%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing perf/update-coefficients (f5c1df7) with perf/update-numbers-only (835d9da)

Open in CodSpeed

Footnotes

  1. 307 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩

FBumann pushed a commit that referenced this pull request Oct 31, 2026
@FBumann FBumann added the perf Wall time, memory, or I/O cost — not a wrong answer label Nov 11, 2026 — with Claude
@FBumann
FBumann marked this pull request as draft November 11, 2026 10:39

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

perf Wall time, memory, or I/O cost — not a wrong answer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants