sourcecode 5.0.1__py3-none-any.whl → 5.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of sourcecode might be problematic. Click here for more details.
- sourcecode/__init__.py +1 -1
- sourcecode/architectural_delta.py +57 -0
- sourcecode/cache_model.py +212 -29
- sourcecode/cli.py +390 -58
- sourcecode/contract_diff.py +27 -0
- sourcecode/execution_plan.py +41 -2
- sourcecode/gate_anchors.py +42 -0
- sourcecode/parse_cache.py +43 -0
- sourcecode/perf.py +168 -16
- sourcecode/verify_edit.py +123 -16
- {sourcecode-5.0.1.dist-info → sourcecode-5.2.0.dist-info}/METADATA +3 -3
- {sourcecode-5.0.1.dist-info → sourcecode-5.2.0.dist-info}/RECORD +15 -14
- {sourcecode-5.0.1.dist-info → sourcecode-5.2.0.dist-info}/WHEEL +0 -0
- {sourcecode-5.0.1.dist-info → sourcecode-5.2.0.dist-info}/entry_points.txt +0 -0
- {sourcecode-5.0.1.dist-info → sourcecode-5.2.0.dist-info}/licenses/LICENSE +0 -0
sourcecode/__init__.py
CHANGED
|
@@ -235,6 +235,63 @@ def diff_metrics(base: ArchMetrics, head: ArchMetrics) -> dict:
|
|
|
235
235
|
}
|
|
236
236
|
|
|
237
237
|
|
|
238
|
+
#: The one sentence both identical-state payloads are derived from (C3-107).
|
|
239
|
+
#: It is an argument, not an assumption, and it rests on a property this product
|
|
240
|
+
#: publishes and asserts every release: the analysis is a pure function of the
|
|
241
|
+
#: tree state, byte-identical across eleven field rounds and two major jumps.
|
|
242
|
+
IDENTICAL_STATE_BASIS = (
|
|
243
|
+
"The two states are one tree, and the analysis is a deterministic function of "
|
|
244
|
+
"the tree state, so every delta is zero without reading the tree. What is "
|
|
245
|
+
"*not* claimed is anything about the tree itself: the per-side totals were "
|
|
246
|
+
"not measured and are `null`, never 0 — pass two different states, or run "
|
|
247
|
+
"`ask <repo>` on one of them, to measure the repository rather than the diff."
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
def identical_state_delta() -> dict:
|
|
252
|
+
"""The `architectural-delta-v1` payload for two states that are one state.
|
|
253
|
+
|
|
254
|
+
C3-107 closed the second build; the eleventh round measured what was left —
|
|
255
|
+
`delta` 24,6 s and `contract-diff` 59,9 s to conclude that a tree does not
|
|
256
|
+
differ from itself, from a purged cache. Building one side to diff it against
|
|
257
|
+
itself is a measurement of the *repository*, and this command's answer is the
|
|
258
|
+
*difference*: with one tree state the difference is empty by construction.
|
|
259
|
+
|
|
260
|
+
So the deltas are published as the zeroes they provably are, and every figure
|
|
261
|
+
that would require an analysis is `null` with the reason attached — the rule
|
|
262
|
+
this product applies everywhere else (an axis that was not measured is
|
|
263
|
+
`unknown`, never `0`).
|
|
264
|
+
"""
|
|
265
|
+
empty_counts = {"base": None, "head": None, "delta": 0}
|
|
266
|
+
return {
|
|
267
|
+
"schema": ARCH_DELTA_SCHEMA,
|
|
268
|
+
"base_cir_hash": None,
|
|
269
|
+
"head_cir_hash": None,
|
|
270
|
+
"totals": {
|
|
271
|
+
"files": dict(empty_counts),
|
|
272
|
+
"symbols": dict(empty_counts),
|
|
273
|
+
"endpoints": dict(empty_counts),
|
|
274
|
+
"dependency_edges": dict(empty_counts),
|
|
275
|
+
"import_cycles": dict(empty_counts),
|
|
276
|
+
},
|
|
277
|
+
"endpoint_surface": {
|
|
278
|
+
"added_count": 0, "removed_count": 0, "added": [], "removed": [],
|
|
279
|
+
},
|
|
280
|
+
"fan_in_shifts": {"changed_count": 0, "shifts": []},
|
|
281
|
+
"import_cycle_shifts": {
|
|
282
|
+
"added_count": 0, "removed_count": 0, "added": [], "removed": [],
|
|
283
|
+
},
|
|
284
|
+
"blast_radius_shifts": {
|
|
285
|
+
"scope": "fan_in_shift_symbols", "changed_count": 0, "shifts": [],
|
|
286
|
+
},
|
|
287
|
+
"analysis": {"performed": False, "basis": IDENTICAL_STATE_BASIS},
|
|
288
|
+
"provenance": (
|
|
289
|
+
"architectural_delta (D1), identical states: no repository was read. "
|
|
290
|
+
+ IDENTICAL_STATE_BASIS
|
|
291
|
+
),
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
|
|
238
295
|
def _transitive_reach(fqn: str, reverse_graph: dict, node_cap: int) -> int:
|
|
239
296
|
"""Size of the transitive reverse-dependency set of `fqn` (its blast radius).
|
|
240
297
|
|
sourcecode/cache_model.py
CHANGED
|
@@ -141,10 +141,11 @@ REFERENCE_JAVA_FILES = 2000
|
|
|
141
141
|
REFERENCE_MEASURED_VERSION = "3.2.2"
|
|
142
142
|
|
|
143
143
|
#: The other end of the measured range, and the reason this module publishes a
|
|
144
|
-
#: *class* rather than a projected duration (C4-19). Field evaluation #
|
|
145
|
-
#: Windows 11 / PowerShell 5.1 / pipx / Python 3.10
|
|
146
|
-
#: 3 342-file repository ran **
|
|
147
|
-
#: 2 000-file reference, for a repository 1,7× the size
|
|
144
|
+
#: *class* rather than a projected duration (C4-19). Field evaluation #26, on
|
|
145
|
+
#: Windows 11 / PowerShell 5.1 / pipx / Python 3.10, every cache purged first:
|
|
146
|
+
#: `spring-audit` on a 3 342-file repository ran **31,0 s** — the same command
|
|
147
|
+
#: takes 8.8 s on the 2 000-file reference, for a repository 1,7× the size, and it
|
|
148
|
+
#: ran 8,4 s on the same subject two releases earlier.
|
|
148
149
|
#:
|
|
149
150
|
#: **The refusal to project stands, and this evaluation strengthened it** (C3-97).
|
|
150
151
|
#: For eight releases the pair of anchors said *cost does not track file count*;
|
|
@@ -159,9 +160,11 @@ REFERENCE_MEASURED_VERSION = "3.2.2"
|
|
|
159
160
|
#: each was measured on**, and how to run it.
|
|
160
161
|
#:
|
|
161
162
|
#: History of the anchor, kept because it is the measurement C3-76 exists for:
|
|
162
|
-
#: 408 s (#13) → 2 351 s (#16, C3-72) → 8,4 s (#22, C3-97)
|
|
163
|
-
#: quoted as an operational anchor for four releases after
|
|
164
|
-
#: it, and told operators to detach commands that finish in
|
|
163
|
+
#: 408 s (#13) → 2 351 s (#16, C3-72) → 8,4 s (#22, C3-97) → 31,0 s (#26, C3-110).
|
|
164
|
+
#: The middle figure was quoted as an operational anchor for four releases after
|
|
165
|
+
#: the build that produced it, and told operators to detach commands that finish in
|
|
166
|
+
#: seconds; the last one moved 3,7× in two releases with byte-identical payloads,
|
|
167
|
+
#: which is the movement the release gate exists to catch and did not.
|
|
165
168
|
#:
|
|
166
169
|
#: ⚠ `FIELD_ANCHOR`, `FIELD_ANCHOR_SECONDS` and `FIELD_ANCHOR_MEASURED_VERSION`
|
|
167
170
|
#: are **derived from the `spring-audit` row**, below `COMMANDS`. They used to be
|
|
@@ -242,12 +245,12 @@ COMMANDS: tuple[CommandCache, ...] = (
|
|
|
242
245
|
"71,7 s again for `--agent` on the state it had just analysed (C3-103).",
|
|
243
246
|
"--compact 13.3 s cold → 0.3 s warm (cold re-measured on 3.7.0: was 19.3 s, C3-6); "
|
|
244
247
|
"--agent --full --env-map --depth 20 34.7 s → 33.9 s (no gain)", analysis_class="repo-wide", cold_seconds=13.3, warm_seconds=0.3,
|
|
245
|
-
field_seconds=
|
|
248
|
+
field_seconds=166.7, field_cache_state="cold", field_measured_version="5.1.0"),
|
|
246
249
|
CommandCache("posture", ("cir", "parse"), "shared", False,
|
|
247
250
|
"Resolves the conditional bean graph on every run, over the shared CIR a warm "
|
|
248
251
|
"builds — the parse it used to repeat for itself. `--diff` compares two profile "
|
|
249
252
|
"sets over that one IR, so the second side costs the resolution only.",
|
|
250
|
-
"10.1 s → 1.6 s", analysis_class="repo-wide", cold_seconds=10.1, warm_seconds=1.6, field_seconds=8.
|
|
253
|
+
"10.1 s → 1.6 s", analysis_class="repo-wide", cold_seconds=10.1, warm_seconds=1.6, field_seconds=8.3, field_cache_state="mixed", field_measured_version="5.1.0"),
|
|
251
254
|
CommandCache("risk", ("cir", "parse"), "shared", False,
|
|
252
255
|
"Composes what the audit, impact-chain and the posture already answer, so it "
|
|
253
256
|
"pays each of their costs once over the shared CIR a warm builds — one parse "
|
|
@@ -255,7 +258,7 @@ COMMANDS: tuple[CommandCache, ...] = (
|
|
|
255
258
|
"within the run.",
|
|
256
259
|
"not measured on the battery yet — the composition is bounded by the "
|
|
257
260
|
"`spring-audit` + `impact-chain` costs listed here, not by new analysis",
|
|
258
|
-
analysis_class="deep", field_seconds=
|
|
261
|
+
analysis_class="deep", field_seconds=77.2, field_cache_state="mixed", field_measured_version="5.1.0"),
|
|
259
262
|
CommandCache("enrich", ("cir", "parse"), "shared", False,
|
|
260
263
|
"Runs the same composition as `risk` over the repository, then joins a SARIF "
|
|
261
264
|
"log to it. Reading the log is negligible; everything a warm helps with is the "
|
|
@@ -280,30 +283,31 @@ COMMANDS: tuple[CommandCache, ...] = (
|
|
|
280
283
|
"builds. Cost scales with the number of declared types, not with the "
|
|
281
284
|
"size of the label.",
|
|
282
285
|
"not measured on the battery yet — one `impact-chain` traversal per "
|
|
283
|
-
"declared seed type over a CIR the warm already paid for", analysis_class="repo-wide"
|
|
286
|
+
"declared seed type over a CIR the warm already paid for", analysis_class="repo-wide",
|
|
287
|
+
field_seconds=28.9, field_cache_state="mixed", field_measured_version="5.1.0"),
|
|
284
288
|
CommandCache("endpoints", ("ris", "parse"), "shared", False,
|
|
285
289
|
"Recomputes the endpoint surface on every run, over a parse a warm has already "
|
|
286
290
|
"paid for. Until 3.7.0 the extractor parsed every file itself instead of reading "
|
|
287
291
|
"the shared parse cache, and a warm measurably bought it nothing (C3-6).",
|
|
288
|
-
"3.3 s → 1.4 s (re-measured on 3.7.0; was 2.8 s → 2.9 s)", analysis_class="repo-wide", cold_seconds=3.3, warm_seconds=1.4, field_seconds=
|
|
292
|
+
"3.3 s → 1.4 s (re-measured on 3.7.0; was 2.8 s → 2.9 s)", analysis_class="repo-wide", cold_seconds=3.3, warm_seconds=1.4, field_seconds=5.6, field_cache_state="mixed", field_measured_version="5.1.0"),
|
|
289
293
|
CommandCache("spring-audit", ("ris", "parse"), "shared", False,
|
|
290
294
|
"Recomputes every run, but over a parse a warm has already paid for.",
|
|
291
|
-
"8.8 s → 3.7 s", analysis_class="repo-wide", cold_seconds=8.8, warm_seconds=3.7, field_seconds=
|
|
295
|
+
"8.8 s → 3.7 s", analysis_class="repo-wide", cold_seconds=8.8, warm_seconds=3.7, field_seconds=31.0, field_cache_state="mixed", field_measured_version="5.1.0"),
|
|
292
296
|
CommandCache("migrate-check", ("cir",), "none", False,
|
|
293
297
|
"Computes its own inventory and shares nothing a warm builds. Only `--blast-radius` "
|
|
294
298
|
"reuses the shared CIR.",
|
|
295
|
-
"4.8 s → 4.8 s", analysis_class="repo-wide", cold_seconds=4.8, warm_seconds=4.8, field_seconds=
|
|
299
|
+
"4.8 s → 4.8 s", analysis_class="repo-wide", cold_seconds=4.8, warm_seconds=4.8, field_seconds=11.3, field_cache_state="mixed", field_measured_version="5.1.0"),
|
|
296
300
|
CommandCache("impact-chain", ("cir", "parse"), "shared", False,
|
|
297
301
|
"The CIR is the expensive half — this is where a warm pays most.",
|
|
298
302
|
"9.9 s → 1.7 s", analysis_class="core", cold_seconds=9.9, warm_seconds=1.7,
|
|
299
|
-
field_seconds=
|
|
303
|
+
field_seconds=16.1, field_cache_state="mixed", field_measured_version="5.1.0"),
|
|
300
304
|
CommandCache("impact", ("parse",), "shared", False, "", "4.9 s → 2.8 s", analysis_class="core", cold_seconds=4.9, warm_seconds=2.8,
|
|
301
305
|
field_seconds=7.7, field_measured_version="4.18.0"),
|
|
302
306
|
CommandCache("pr-impact", ("parse",), "shared", False,
|
|
303
307
|
"Diff-dependent: the answer itself is never stored. What it costs follows the "
|
|
304
308
|
"diff, not the repository: 12,5 s on an ordinary one and 11,8 s on a diff of "
|
|
305
309
|
"security configuration, measured at field scale.", analysis_class="core",
|
|
306
|
-
field_seconds=
|
|
310
|
+
field_seconds=25.7, field_cache_state="mixed", field_measured_version="5.1.0"),
|
|
307
311
|
CommandCache("verify", (), "none", False, "Runs the contracts against a fresh reading.", analysis_class="core"),
|
|
308
312
|
CommandCache("verify-edit", ("parse",), "shared", True,
|
|
309
313
|
"Built for the edit loop: the parse cache is what keeps an unchanged file out of the "
|
|
@@ -311,15 +315,17 @@ COMMANDS: tuple[CommandCache, ...] = (
|
|
|
311
315
|
"yet: eval #23 measured 76,6 s on a tree with no edits, because the HEAD side is "
|
|
312
316
|
"still built in a throwaway worktree instead of reusing the shared CIR (C3-102).",
|
|
313
317
|
"14.6 s → 9.6 s → 5.6 s on repeat", analysis_class="repo-wide", cold_seconds=14.6, warm_seconds=9.6,
|
|
314
|
-
field_seconds=
|
|
318
|
+
field_seconds=119.5, field_cache_state="mixed", field_measured_version="5.1.0"),
|
|
315
319
|
CommandCache("review-pr", ("cir",), "none", False,
|
|
316
320
|
"Diff-dependent, and it reuses the CIR only if one exists. On a small diff, loading "
|
|
317
321
|
"the warmed CIR costs more than the work it saves.",
|
|
318
322
|
"1.1 s → 2.3 s (slower)", analysis_class="core", cold_seconds=1.1, warm_seconds=2.3),
|
|
319
323
|
CommandCache("plan", ("parse",), "shared", False, "", "9.3 s → 3.8 s", analysis_class="core", cold_seconds=9.3, warm_seconds=3.8),
|
|
320
324
|
CommandCache("compare", ("parse",), "shared", False, "", analysis_class="core"),
|
|
321
|
-
CommandCache("delta", (), "none", False, "Analyses two states — two checkouts, or two refs materialised into temporary trees; neither is the tree the cache describes.", analysis_class="repo-wide"
|
|
322
|
-
|
|
325
|
+
CommandCache("delta", (), "none", False, "Analyses two states — two checkouts, or two refs materialised into temporary trees; neither is the tree the cache describes.", analysis_class="repo-wide",
|
|
326
|
+
field_seconds=24.6, field_cache_state="mixed", field_measured_version="5.1.0"),
|
|
327
|
+
CommandCache("contract-diff", (), "none", False, "Analyses two states (checkouts or refs); neither is the tree the cache describes.", analysis_class="repo-wide",
|
|
328
|
+
field_seconds=59.9, field_cache_state="mixed", field_measured_version="5.1.0"),
|
|
323
329
|
CommandCache("fix-bug", ("task",), "none", True,
|
|
324
330
|
"Shorthand for `prepare-context fix-bug`; caches its own answer, which a warm never runs.", analysis_class="core"),
|
|
325
331
|
CommandCache("rename-class", (), "none", False, "", analysis_class="core"),
|
|
@@ -341,26 +347,27 @@ COMMANDS: tuple[CommandCache, ...] = (
|
|
|
341
347
|
"no answer hit", analysis_class="repo-wide", cold_seconds=6.5, warm_seconds=0.3),
|
|
342
348
|
CommandCache("explain", ("cir",), "shared", False, "Serves from the shared CIR a warm builds.",
|
|
343
349
|
"9.8 s → 1.6 s", analysis_class="core", cold_seconds=9.8, warm_seconds=1.6,
|
|
344
|
-
field_seconds=
|
|
350
|
+
field_seconds=6.3, field_cache_state="mixed", field_measured_version="5.1.0"),
|
|
345
351
|
CommandCache("export", ("parse",), "shared", False, "", "8.8 s → 3.7 s", analysis_class="repo-wide", cold_seconds=8.8, warm_seconds=3.7),
|
|
346
352
|
CommandCache("repo-ir", ("parse",), "shared", False,
|
|
347
353
|
"Carried as *did not finish* from 4.10.4 until eval #23 ran it at field size in "
|
|
348
354
|
"9,8 s — a run that did not finish once is not a command that cannot finish "
|
|
349
355
|
"(C3-100, and the same correction `modernize` needed).",
|
|
350
356
|
"5.1 s → 2.9 s", analysis_class="repo-wide", cold_seconds=5.1, warm_seconds=2.9,
|
|
351
|
-
field_seconds=
|
|
357
|
+
field_seconds=19.2, field_cache_state="mixed", field_measured_version="5.1.0"),
|
|
352
358
|
CommandCache("validation", ("parse",), "shared", False, "", "11.6 s → 6.4 s", analysis_class="repo-wide", cold_seconds=11.6, warm_seconds=6.4,
|
|
353
|
-
field_seconds=
|
|
359
|
+
field_seconds=39.5, field_cache_state="mixed", field_measured_version="5.1.0"),
|
|
354
360
|
CommandCache("modernize", ("parse",), "shared", False,
|
|
355
361
|
"Blocked in the session that recorded C3-53 and measured since: a run that did "
|
|
356
362
|
"not finish once is not a command that cannot finish.",
|
|
357
363
|
"5.2 s → 3.0 s", analysis_class="repo-wide", cold_seconds=5.2, warm_seconds=3.0,
|
|
358
|
-
field_seconds=
|
|
364
|
+
field_seconds=17.1, field_cache_state="mixed", field_measured_version="5.1.0"),
|
|
359
365
|
CommandCache("chunk-file", (), "none", False, "Reads one file; nothing to cache.", analysis_class="core"),
|
|
360
366
|
CommandCache("cold-start", ("ris",), "answer", True,
|
|
361
367
|
"Reads the RIS a warm rebuilds — that is all it does. Without one it answers "
|
|
362
368
|
"`no_ris` instead of a snapshot.",
|
|
363
|
-
"0.2 s either way", analysis_class="core", cold_seconds=0.2, warm_seconds=0.2
|
|
369
|
+
"0.2 s either way", analysis_class="core", cold_seconds=0.2, warm_seconds=0.2,
|
|
370
|
+
field_seconds=0.4, field_cache_state="mixed", field_measured_version="5.1.0"),
|
|
364
371
|
CommandCache("trend", (), "none", False, "Reads stored baseline artifacts from disk; analyses no source, so no cache layer applies. Same command as `baseline trend`.", analysis_class="none"),
|
|
365
372
|
CommandCache("baseline", ("parse",), "shared", False,
|
|
366
373
|
"`capture`/`diff`/`trend` over architectural metrics. The field figure is `capture`, "
|
|
@@ -405,13 +412,15 @@ def _row(command: str) -> "CommandCache":
|
|
|
405
412
|
|
|
406
413
|
#: The headline anchor, read off the table rather than written twice (C3-100).
|
|
407
414
|
#: `spring-audit` is the command the whole series measured — 408 s (#13), 2 351 s
|
|
408
|
-
#: (#16), 8,4 s (#22) — so it is the row the front page quotes, and
|
|
409
|
-
#: means reading it, not copying it.
|
|
415
|
+
#: (#16), 8,4 s (#22), 31,0 s (#26) — so it is the row the front page quotes, and
|
|
416
|
+
#: quoting it means reading it, not copying it. The figure moving *up* between two
|
|
417
|
+
#: rounds with byte-identical payloads is the reason C3-110 exists: nothing in this
|
|
418
|
+
#: repository measured the direction, and the anchor is the only place it shows.
|
|
410
419
|
_FIELD_ANCHOR_ROW = _row("spring-audit")
|
|
411
420
|
FIELD_ANCHOR_SECONDS = _FIELD_ANCHOR_ROW.field_seconds
|
|
412
421
|
FIELD_ANCHOR_MEASURED_VERSION = _FIELD_ANCHOR_ROW.field_measured_version
|
|
413
422
|
FIELD_ANCHOR = (
|
|
414
|
-
f"field evaluation #
|
|
423
|
+
f"field evaluation #26: spring-audit on {_thousands(FIELD_ANCHOR_JAVA_FILES)} "
|
|
415
424
|
f"Java files took {FIELD_ANCHOR_SECONDS:g} s (Windows, pipx, "
|
|
416
425
|
f"{_FIELD_ANCHOR_ROW.field_cache_state} cache) against "
|
|
417
426
|
f"{_FIELD_ANCHOR_ROW.cold_seconds:g} s on the "
|
|
@@ -532,6 +541,37 @@ def field_anchor_note(row: "Optional[CommandCache]") -> "Optional[str]":
|
|
|
532
541
|
return f"on {measured_on}"
|
|
533
542
|
|
|
534
543
|
|
|
544
|
+
def field_anchor_currency_clause(row: "Optional[CommandCache]") -> "Optional[str]":
|
|
545
|
+
"""The same fact as :func:`field_anchor_note`, said where it is *acted on* (C3-110).
|
|
546
|
+
|
|
547
|
+
C3-109 made every field figure carry its build, and the eleventh round confirms
|
|
548
|
+
the label is read and believed — and then reports the gap it does not close:
|
|
549
|
+
`spring-audit` publishes *"8,4 s … (4.18.0)"* while the same command measures
|
|
550
|
+
31,0 s on the build the reader is running. `(on 4.18.0)` is the right label for
|
|
551
|
+
a **row in a table**, where the reader is comparing figures; it is not enough
|
|
552
|
+
on a line that tells somebody how to run something, because there the figure is
|
|
553
|
+
being used as advice about the build in hand.
|
|
554
|
+
|
|
555
|
+
So the same fact gets a longer form for the surfaces that advise: the build,
|
|
556
|
+
and the admission that nothing has re-measured it here. That admission is the
|
|
557
|
+
registry this product applies everywhere else (`counts_are_floor`,
|
|
558
|
+
`unchanged_for`, `confidence_basis`) and the one place it had not applied to
|
|
559
|
+
itself.
|
|
560
|
+
|
|
561
|
+
``None`` when the figure was taken on the running build — there is nothing to
|
|
562
|
+
admit — or when there is no figure at all.
|
|
563
|
+
"""
|
|
564
|
+
if row is None or (row.field_seconds is None and not row.field_blocked):
|
|
565
|
+
return None
|
|
566
|
+
from sourcecode import __version__
|
|
567
|
+
|
|
568
|
+
measured_on = row.field_measured_version
|
|
569
|
+
if measured_on == __version__:
|
|
570
|
+
return None
|
|
571
|
+
where = f"measured on {measured_on}" if measured_on else "build not recorded"
|
|
572
|
+
return f"{where}; this build has not been re-measured at that scale"
|
|
573
|
+
|
|
574
|
+
|
|
535
575
|
def cost_sentence() -> str:
|
|
536
576
|
"""The one paragraph the front page says about cost, derived here (CL-21).
|
|
537
577
|
|
|
@@ -544,15 +584,38 @@ def cost_sentence() -> str:
|
|
|
544
584
|
with. It is generated from the anchors instead, so refreshing them refreshes
|
|
545
585
|
the prose.
|
|
546
586
|
"""
|
|
587
|
+
from sourcecode import __version__
|
|
588
|
+
|
|
547
589
|
audit = next((r for r in COMMANDS if r.command == "spring-audit"), None)
|
|
548
590
|
seconds = FIELD_ANCHOR_SECONDS if audit is None or audit.field_seconds is None else audit.field_seconds
|
|
591
|
+
# C3-110: the figure is history the moment it is published, and this sentence
|
|
592
|
+
# is the surface a reader budgets against. The field measured 31,0 s where this
|
|
593
|
+
# line said 8,4 s, and the line was not wrong — it named 4.18.0 — it just left
|
|
594
|
+
# the reader to notice that 4.18.0 is not the build they are running. Said
|
|
595
|
+
# outright, and paired with the one figure this project *can* refresh: the gate
|
|
596
|
+
# measurement of the build in hand, when there is one.
|
|
597
|
+
stale = (
|
|
598
|
+
""
|
|
599
|
+
if FIELD_ANCHOR_MEASURED_VERSION == __version__
|
|
600
|
+
else f", and {__version__} has not been re-measured at that scale"
|
|
601
|
+
)
|
|
602
|
+
gate = ""
|
|
603
|
+
_gate_cell = gate_anchor("spring-audit")
|
|
604
|
+
_gate_state = gate_currency()
|
|
605
|
+
if _gate_cell and _gate_state.get("current"):
|
|
606
|
+
gate = (
|
|
607
|
+
f" On this build the release gate measured the same command at "
|
|
608
|
+
f"{_gate_cell['seconds']:g} s on a "
|
|
609
|
+
f"{_thousands(int(_gate_cell['java_files']))}-file repository "
|
|
610
|
+
f"({_gate_cell['cache_state']} cache, {_gate_cell['host_class']})."
|
|
611
|
+
)
|
|
549
612
|
return (
|
|
550
613
|
f"Cost tracks the command class and the build, not the file count: "
|
|
551
614
|
f"per-symbol queries are the fast path, inventory commands scale with "
|
|
552
615
|
f"files, and a repository-wide audit measured {seconds:g} s on a "
|
|
553
616
|
f"{_thousands(FIELD_ANCHOR_JAVA_FILES)}-file repository "
|
|
554
|
-
f"({FIELD_ANCHOR_MEASURED_VERSION}). `ask cache model` prints
|
|
555
|
-
f"and the build behind it for every command; "
|
|
617
|
+
f"({FIELD_ANCHOR_MEASURED_VERSION}{stale}).{gate} `ask cache model` prints "
|
|
618
|
+
f"the figure and the build behind it for every command; "
|
|
556
619
|
f"ASK_MAX_ANALYSIS_SECONDS/ASK_PROGRESS bound and narrate a run where CI "
|
|
557
620
|
f"wants an explicit budget."
|
|
558
621
|
)
|
|
@@ -616,6 +679,103 @@ def field_currency() -> dict:
|
|
|
616
679
|
}
|
|
617
680
|
|
|
618
681
|
|
|
682
|
+
def gate_anchor(command: str) -> "Optional[dict]":
|
|
683
|
+
"""What the release gate measured for *command*, or ``None`` (C3-109).
|
|
684
|
+
|
|
685
|
+
The third figure in this module, and the only one this repository can refresh
|
|
686
|
+
by itself. `REFERENCE_*` is a 3.2.2 measurement on a 2 000-file tree;
|
|
687
|
+
`field_seconds` is the field's, at 3 342 files, on their machine and their
|
|
688
|
+
build. Both age, and neither can be re-measured from here — which is exactly
|
|
689
|
+
how B17 reopened one release after it was closed: the labelling worked and
|
|
690
|
+
the number still expired.
|
|
691
|
+
|
|
692
|
+
The gate measures a 2 985-file repository under a declared host class every
|
|
693
|
+
release and commits its cells, so this figure carries the build that produced
|
|
694
|
+
it and can be brought current by running the gate. It never overrides a field
|
|
695
|
+
anchor — a measurement at field scale outranks one at gate scale — it is
|
|
696
|
+
published *beside* it, so an anchor from an older build is no longer the only
|
|
697
|
+
number a reader has.
|
|
698
|
+
"""
|
|
699
|
+
try:
|
|
700
|
+
from sourcecode.gate_anchors import (
|
|
701
|
+
GATE_ANCHORS,
|
|
702
|
+
GATE_HOST_CLASS,
|
|
703
|
+
GATE_JAVA_FILES,
|
|
704
|
+
GATE_MEASURED_VERSION,
|
|
705
|
+
GATE_REPOSITORY,
|
|
706
|
+
)
|
|
707
|
+
except Exception:
|
|
708
|
+
return None
|
|
709
|
+
cell = GATE_ANCHORS.get(command)
|
|
710
|
+
if not cell:
|
|
711
|
+
return None
|
|
712
|
+
return {
|
|
713
|
+
"seconds": cell["seconds"],
|
|
714
|
+
"cache_state": cell["mode"],
|
|
715
|
+
"runs": cell["runs"],
|
|
716
|
+
"measured_on_version": GATE_MEASURED_VERSION,
|
|
717
|
+
"repository": GATE_REPOSITORY,
|
|
718
|
+
"java_files": GATE_JAVA_FILES,
|
|
719
|
+
"host_class": GATE_HOST_CLASS,
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
|
|
723
|
+
def gate_currency() -> dict:
|
|
724
|
+
"""Whether the in-house gate figures describe the build in hand (C3-109).
|
|
725
|
+
|
|
726
|
+
Same shape and same purpose as `field_currency`, for the anchor set that can
|
|
727
|
+
actually be refreshed. When this says `current: false`, the remedy is a
|
|
728
|
+
command rather than a hope: re-run the gate on the tag and commit the cells.
|
|
729
|
+
"""
|
|
730
|
+
from sourcecode import __version__
|
|
731
|
+
|
|
732
|
+
current = __version__
|
|
733
|
+
try:
|
|
734
|
+
from sourcecode.gate_anchors import (
|
|
735
|
+
GATE_ANCHORS,
|
|
736
|
+
GATE_CAPTURED_AT,
|
|
737
|
+
GATE_HOST_CLASS,
|
|
738
|
+
GATE_JAVA_FILES,
|
|
739
|
+
GATE_MEASURED_VERSION,
|
|
740
|
+
GATE_REPOSITORY,
|
|
741
|
+
)
|
|
742
|
+
except Exception:
|
|
743
|
+
return {
|
|
744
|
+
"available": False,
|
|
745
|
+
"running_version": current,
|
|
746
|
+
"statement": (
|
|
747
|
+
"This build carries no gate measurement of its own. The gate "
|
|
748
|
+
"publishes one per release (docs/perf/REGRESSION-GATE.md); until "
|
|
749
|
+
"it runs, the field anchors are the only measured figures here."
|
|
750
|
+
),
|
|
751
|
+
}
|
|
752
|
+
return {
|
|
753
|
+
"available": True,
|
|
754
|
+
"measured_on_version": GATE_MEASURED_VERSION,
|
|
755
|
+
"running_version": current,
|
|
756
|
+
"current": GATE_MEASURED_VERSION == current,
|
|
757
|
+
"captured_at": GATE_CAPTURED_AT,
|
|
758
|
+
"repository": GATE_REPOSITORY,
|
|
759
|
+
"java_files": GATE_JAVA_FILES,
|
|
760
|
+
"host_class": GATE_HOST_CLASS,
|
|
761
|
+
"commands": sorted(GATE_ANCHORS),
|
|
762
|
+
"statement": (
|
|
763
|
+
f"The release gate measured {len(GATE_ANCHORS)} commands on "
|
|
764
|
+
f"{GATE_REPOSITORY} ({GATE_JAVA_FILES} Java files, {GATE_HOST_CLASS}) "
|
|
765
|
+
+ (
|
|
766
|
+
f"on {current}, the build you are running."
|
|
767
|
+
if GATE_MEASURED_VERSION == current
|
|
768
|
+
else (
|
|
769
|
+
f"on {GATE_MEASURED_VERSION}; you are running {current}, which "
|
|
770
|
+
f"the gate has not measured. Re-run it on this build "
|
|
771
|
+
f"(docs/perf/REGRESSION-GATE.md) — unlike the field anchors, "
|
|
772
|
+
f"this is a figure this project can refresh."
|
|
773
|
+
)
|
|
774
|
+
)
|
|
775
|
+
),
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
|
|
619
779
|
def reference_currency() -> dict:
|
|
620
780
|
"""How old the reference figures are, in releases the reader can name (F-AP).
|
|
621
781
|
|
|
@@ -680,6 +840,11 @@ def as_dict(here: "Optional[Conditioning]" = None) -> dict:
|
|
|
680
840
|
# measured 2 351 s and 8,4 s on two of our own builds (C4-19, C3-97).
|
|
681
841
|
"field_anchor": FIELD_ANCHOR,
|
|
682
842
|
"field_currency": field_currency(),
|
|
843
|
+
# C3-109: and the figure this project can refresh by itself. A field
|
|
844
|
+
# anchor belongs to the build the field ran; this one belongs to the
|
|
845
|
+
# build the gate ran, which is a release away at worst instead of
|
|
846
|
+
# unreachable. Published beside, never instead.
|
|
847
|
+
"gate_currency": gate_currency(),
|
|
683
848
|
"commands": [
|
|
684
849
|
{
|
|
685
850
|
"command": cmd.command,
|
|
@@ -716,6 +881,12 @@ def as_dict(here: "Optional[Conditioning]" = None) -> dict:
|
|
|
716
881
|
"note": field_anchor_note(cmd),
|
|
717
882
|
}
|
|
718
883
|
),
|
|
884
|
+
# C3-109: the in-house measurement of this command, on the build
|
|
885
|
+
# the gate last ran. Absent for commands the gate does not cover —
|
|
886
|
+
# its population is declared in `sourcecode.perf`, with the
|
|
887
|
+
# exclusions and their reasons, and an axis nobody measured is
|
|
888
|
+
# never a number here.
|
|
889
|
+
"gate_measurement": gate_anchor(cmd.command),
|
|
719
890
|
}
|
|
720
891
|
for cmd in COMMANDS
|
|
721
892
|
],
|
|
@@ -827,6 +998,7 @@ def render_text(here: "Optional[Conditioning]" = None) -> str:
|
|
|
827
998
|
lines.append(f" Timings: {REFERENCE_REPOSITORY}, each command measured in isolation.")
|
|
828
999
|
lines.append(f" {reference_currency()['statement']}")
|
|
829
1000
|
lines.append(f" {field_currency()['statement']}")
|
|
1001
|
+
lines.append(f" {gate_currency()['statement']}")
|
|
830
1002
|
width = max(len(c.command) for c in COMMANDS)
|
|
831
1003
|
for cmd in COMMANDS:
|
|
832
1004
|
repeat = "repeat cached" if cmd.repeat else "recomputes"
|
|
@@ -848,6 +1020,17 @@ def render_text(here: "Optional[Conditioning]" = None) -> str:
|
|
|
848
1020
|
f" {' ' * width} field: {shown} at "
|
|
849
1021
|
f"{_thousands(FIELD_ANCHOR_JAVA_FILES)} Java files{suffix}"
|
|
850
1022
|
)
|
|
1023
|
+
_gate = gate_anchor(cmd.command)
|
|
1024
|
+
if _gate:
|
|
1025
|
+
# C3-109: the in-house figure, beside the field's rather than instead
|
|
1026
|
+
# of it — one is at field scale on another build, one is on a build
|
|
1027
|
+
# this project can bring current.
|
|
1028
|
+
lines.append(
|
|
1029
|
+
f" {' ' * width} gate: {_gate['seconds']:g} s at "
|
|
1030
|
+
f"{_thousands(_gate['java_files'])} Java files "
|
|
1031
|
+
f"({_gate['cache_state']} cache, on {_gate['measured_on_version']}, "
|
|
1032
|
+
f"{_gate['host_class']})"
|
|
1033
|
+
)
|
|
851
1034
|
if cmd.note:
|
|
852
1035
|
lines.append(f" {' ' * width} {cmd.note}")
|
|
853
1036
|
if here is not None and cmd.command in here.per_command:
|