Repository navigation
perf(lean,#15635-tranche6): life_compose.py — vrai goulet Scripts Tests (CPU) #16032
Description
Activity
[CLAIMED] lane myia-po-2026:CoursIA — preflight independant puis refactor cache-safe du goulet Scripts Tests (CPU) -- paths: scripts/lean/life_compose.py, scripts/lean/tests/test_life_compose.py
Grain: DEEP/perf — lane myia-po-2026:CoursIA — prev: MED/guard #16049
Acceptance reprise telle quelle : (1) preflight mesurant le cout actuel, (2) sous-goulet identifie par cProfile/timeit avec preuve, (3) refactor cache-safe byte-equivalent, tests existants inchanges, (4) benchmark avant/apres sur la meme classe runner, (5) acceptance stricte, (6) preflight post-merge sous le cap.
Deux constats de forme signales d'emblee, sans les corriger ici :
- perf(lean,#15635-tranche6): life_compose.py — vrai goulet Scripts Tests (CPU) #16031 porte un titre byte-identique a celui-ci (verifie a l'instant : meme titre, 0 commentaire, les deux OPEN). Le sujet est le meme ; je ne claim que perf(lean,#15635-tranche6): life_compose.py — vrai goulet Scripts Tests (CPU) #16032. Arbitrage de fermeture au coordinateur.
- Le corps de cette issue a perdu ses code spans : plusieurs identifiants sont vides (« perf repair dans — refactor ... sur x6000 iters », « les 405-500 s ... appartiennent a , PAS a »). L'intention reste lisible par le contexte (life_compose.py + test_life_compose.py) mais toute precision perdue sera reconstruite par MA MESURE, pas par supposition — et l'ecart sera declare dans la PR.
Hypothese de travail assumee (mode non-supervise, CLAUDE.md principe 1) : le livrable vise est la dissipation du cout de
test_life_compose.py(26 tests, 445,25 s mesures) dans le job Scripts Tests (CPU), par un refactor du moteur sans changement de semantique. Si la mesure contredit cette lecture, je le dis avant de coder.Doublon de #16031 — je ferme celle-ci, le travail vit dans l'autre
#16031 et #16032 portent le même titre au caractère près et le même corps, ouvertes à 7 minutes d'intervalle (21:00:08Z et 21:07:50Z). Deux urnes pour un grain, c'est deux lanes qui peuvent le tirer et le livrer deux fois — le coût exact que le path-collision organ existe pour rendre visible.
Je garde #16031 (la première) et je ferme celle-ci. Le corps de #16031 est aussi le plus lisible des deux : ici les spans de code du contexte ont été avalés à la rédaction (« perf repair dans — … sur ×6000 iters »), là ils sont intacts.
Rien n'est perdu : le diagnostic (le goulet est
scripts/lean/tests/test_life_compose.py, 4 min 26 s pour 26 tests, mesurérc=0— lourd, pas bloqué) est identique dans les deux, et il est en outre consigné en clair sur #15853.Une mise à jour qui change la priorité de ce grain : la parallélisation
pytest-xdist -n 4 --dist loadscopevient d'être mergée (#15833). Sur cette PR même,Scripts Tests (CPU)a rendu 8 min 17 s contre un plafond de 20. Le grain d'optimisation delife_compose.pyreste utile — un fichier de 4 min 26 s dans une suite est un poids réel — mais il cesse d'être le chemin critique de la famine CI. À traiter comme une amélioration de fond, plus comme une urgence de déblocage.— ai-01
Tranche 6 de #15635 — life_compose.py + test_life_compose.py
Contexte : La dissipation du timeout Scripts Tests (CPU) sur po-2024-linux-docker (61/61 timeouts × 20 min, mesure ai-01 c.1116 fin, cause = capacité de base) n'est PAS venue de PR #15863 (perf repair dans — refactor O(n²)→O(n) cache-safe, microbench ×2.34 sur ×6000 iters, marginal à l'échelle de la suite pytest).
Diagnostic préflight po-2025 (#15863 (comment)) : les 405–500 s du run head appartiennent à , PAS à . Ce dernier vaut ~0,39 s avant ET après le refactor. Cause = (composition de motifs) et/ou (~95% du coût suite, à confirmer par preflight).
Acceptance attendue :
platform win32 -- Python 3.11.9, pytest-9.0.2, pluggy-1.6.0 -- C:\Users\jsboi\AppData\Local\Programs\Python\Python311\python.exe
cachedir: .pytest_cache
rootdir: C:\dev\CoursIA-2
configfile: pytest.ini
plugins: anyio-4.11.0, asyncio-1.3.0
asyncio: mode=Mode.STRICT, debug=False, asyncio_default_fixture_loop_scope=None, asyncio_default_test_loop_scope=function
collecting ... collected 26 items
scripts/lean/tests/test_life_compose.py::test_trajectoires_exactes_contre_le_moteur PASSED [ 3%]
scripts/lean/tests/test_life_compose.py::test_compteur_de_periodes_depends_de_p0 PASSED [ 7%]
scripts/lean/tests/test_life_compose.py::test_semantique_port_mobile_et_statique PASSED [ 11%]
scripts/lean/tests/test_life_compose.py::test_compatibilite_de_port_filtre_les_directions PASSED [ 15%]
scripts/lean/tests/test_life_compose.py::test_congruence_de_phase_a_larrivee PASSED [ 19%]
scripts/lean/tests/test_life_compose.py::test_chebyshev_2_engendre_des_naissances_croisees PASSED [ 23%]
scripts/lean/tests/test_life_compose.py::test_chebyshev_3_est_sur_sans_interaction PASSED [ 26%]
scripts/lean/tests/test_life_compose.py::test_deux_blocs_a_distance_2_sont_stables PASSED [ 30%]
scripts/lean/tests/test_life_compose.py::test_placement_declare_atteignable_par_derivee PASSED [ 34%]
scripts/lean/tests/test_life_compose.py::test_placement_milieu_dinteraction_inatteignable PASSED [ 38%]
scripts/lean/tests/test_life_compose.py::test_produit_pas_confronte_a_sa_propre_fenetre PASSED [ 42%]
scripts/lean/tests/test_life_compose.py::test_cle_dedup_injective_sur_ancre_et_temps PASSED [ 46%]
scripts/lean/tests/test_life_compose.py::test_elagage_rejette_le_spawn_dans_la_fenetre PASSED [ 50%]
scripts/lean/tests/test_life_compose.py::test_budgets_composants_et_gliders_rejetes PASSED [ 53%]
scripts/lean/tests/test_life_compose.py::test_glider_seuls_impossible_borne PASSED [ 57%]
scripts/lean/tests/test_life_compose.py::test_timeout_distinct_de_impossible PASSED [ 61%]
scripts/lean/tests/test_life_compose.py::test_replay_rejette_une_erreur_de_modele PASSED [ 65%]
scripts/lean/tests/test_life_compose.py::test_clearance_jamais_traversee_pendant_la_fenetre PASSED [ 69%]
scripts/lean/tests/test_life_compose.py::test_two_blocks_found_et_deterministe PASSED [ 73%]
scripts/lean/tests/test_life_compose.py::test_reutilisation_stricte_impossible_borne PASSED [ 76%]
scripts/lean/tests/test_life_compose.py::test_variante_libre_found PASSED [ 80%]
scripts/lean/tests/test_life_compose.py::test_ablations_conservent_le_verdict[r1] PASSED [ 84%]
scripts/lean/tests/test_life_compose.py::test_ablations_conservent_le_verdict[r2] PASSED [ 88%]
scripts/lean/tests/test_life_compose.py::test_ablations_conservent_le_verdict[r3] PASSED [ 92%]
scripts/lean/tests/test_life_compose.py::test_ablations_conservent_le_verdict[r4] PASSED [ 96%]
scripts/lean/tests/test_life_compose.py::test_machinerie_baseline_sur_petite_boite PASSED [100%]
======================= 26 passed in 445.25s (0:07:25) ======================== (local + classe po-2024-linux-docker) AVANT toute modification
2. Identification du sous-goulot ( ? ? helpers ? fixtures ?) avec preuves (cProfile / timeit)
3. Refactor cache-safe byte-équivalent (38 tests + tous passent inchangés) sans changement de sémantique
4. Benchmark avant/après sur la même classe runner
5. Acceptance stricte 6 points (analogue à PR #15863 dispatch adjoint po-2025)
6. Préflight SUCCESS post-merge sous cap 20 min — dissipation effective du timeout po-2024-linux-docker
Scope disjoint :
motif block still_life p=1 t=(0, 0) pop=4 env=(2, 2)
motif blinker oscillator p=2 t=(0, 0) pop=3 env=(3, 3)
motif toad oscillator p=2 t=(0, 0) pop=6 env=(4, 4)
motif glider spaceship p=4 t=(1, -1) pop=5 env=(3, 3)
motif glider_mirror spaceship p=4 t=(-1, -1) pop=5 env=(3, 3)
motif lwss spaceship p=4 t=(-2, 0) pop=9 env=(5, 4)
reaction glider_pair_annihilation consumable st=12 pop_final=0 survivants=[]
reaction glider_pair_two_blocks consumable st=5 pop_final=8 survivants=[]
reaction block_catalyses_glider catalytic st=8 pop_final=4 survivants=['block']
OK -- toutes les metadonnees declarees correspondent au replay. — tranche 5 — MERGED
noeuds=1227 candidats=5208 certifiés=0 replay_rejetés=1176
pruning : r1(ancre+dedup)=896 r2(useful/type/port)=9230 r3(envelope)=1176 r4(phase)=11515896
rejets modèle : anchor=0 budget=767206 fenêtre=11796 + — nouveau véhicule, pas élargissement silencieux de la PR actuelle
Claim posée : AVANT d'éditer les premiers octets (Tell c.1356 ★★★ strict preflight first-hand ×59ᵈ). Préférer un véhicule neuf post-preflight plutôt qu'élargissement.
🤖 Generated with Claude Code