Conversation
benchmarks/bench.py times the phases of the solver's main workloads (3D elastic, 2D Poisson P1 and P2, Newton St-VK, heat stepping, adaptive refinement, SIMP, Ruppert, red-green, modal) at the sizes of the 2026-09-03 performance audit or a --quick preset, printing one table and optionally appending JSON records. It is the before/after table for a PR that touches a hot path, run by hand; timing is not gated in CI. tests/test_perf_contracts.py asserts the counts that fix a path's cost through a CountingBackend in tests/helpers.py: LinearSolve factors once and solves once, ThetaMethod factors once over all steps, Newmark factors twice, the sensitivity analysis shares one factorization and skips the self-adjoint adjoint solve, the direct ordering's fill stays under 8x nnz(A) where COLAMD exceeds it, and AMG-CG's matvec count stays bounded on a mesh doubling. benchmarks is added to pyright's include so the script stays type-checked.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two pieces from the performance audit's "how do we measure progress" question: a benchmark script for the timing side, run by hand, and count-based contract tests for the regression side, run in CI.
benchmarks/bench.pyPhase timings of the solver's main workloads: 3D linear elastic (build, direct, AMG-CG, both stress recoveries), 2D Poisson P1 and P2 (build, both backends, both gradient recoveries, both estimators), Newton St-VK P1 and P2,
ThetaMethodheat with constant and withTimeDependentdata,AdaptiveRefinementwith each estimator, SIMP, Ruppert at two area caps,RedGreenRefiner, andModalAnalysison a P2 beam. The default sizes are those ofattic/performance-audit-2026-09-03.mdsection 1 (a few minutes);--quickruns every workload in about 25 s.--onlypicks workloads and--json PATHappends one record per phase (commit, timestamp, numpy/scipy/pyamg versions, workload, phase, seconds) as JSON lines.It exists to produce a before/after table to paste into a PR that touches a hot path. Ratios within one run on one machine are meaningful; absolutes are not (one laptop drifted 3x in a day; CI runners differ), so it is not in CI and not a threshold test.
benchmarksis added to pyright's include list so the script stays type-checked; ruff already covers it.tests/test_perf_contracts.pyWhat makes a path fast is countable and deterministic, so these assert counts through a
CountingBackend(new intests/helpers.py, wrapping any backend and countingpreparecalls and factorization solves):LinearSolvefactors exactly once and back-substitutes exactly once.ThetaMethodover N steps factors once and solves N times.NewmarkMethodover N steps factors exactly twice (the mass for the initial acceleration, then the effective operator) and solves N + 1 times.SensitivityAnalysisshares one factorization between forward and adjoint; a self-adjoint QoI (Complianceunder homogeneous supports) makes no adjoint solve,PointValueexactly one.DirectBackend's ordering keeps L + U fill under 8x nnz(A) on a 100x100 P1 Poisson block (5.3x today), and the test checks that scipy's default COLAMD ordering exceeds the same bound (12.2x), so the bound really separates the two.LinearOperatorinto the CG solver's operator, a private attribute, noted in the test.Sourcecontract from Source: integrate a constant load element-wise, optimize the sampled contraction #172 (tests/test_loads.py) is referenced as part of the set rather than duplicated.A last test checks the counting wrapper changes nothing but the counts.
Verification
Full suite 1122 passed (including the 7 new tests);
ruff checkandpyrightclean over the whole repo with the new include. Quick preset on this branch (dcd55fabase, one laptop):