Skip to content

perf: la CI valide en une minute et demie au lieu de quatre - #47

Merged
lostmind84 merged 3 commits into
mainfrom
perf/la-ci-ne-dure-plus-que-son-etape-la-plus-longue
Aug 2, 2026
Merged

lostmind84 merged 3 commits into
mainfrom
perf/la-ci-ne-dure-plus-que-son-etape-la-plus-longue

Conversation

@lostmind84

Copy link
Copy Markdown
Owner

La CI mettait 3 min 55 à valider une pull request, dont 3 min 51 pour le seul
travail « Tests et frontières ». Les trois autres travaux avaient fini depuis plus de
deux minutes.

Deux causes, mesurées avant d'être corrigées.

Le coût argon2 d'un vrai login, payé par chaque montage de test

internal/web mettait 59,5 s dans la passe -race — le paquet le plus lourd du
dépôt, à lui seul près de la moitié de la passe. Ses tests écrivaient leurs empreintes
avec HashSecret, donc au coût d'un login sur l'i3 du poste : argon2id, 64 MiB, t=3,
p=2. Trente-quatre montages en écrivent deux chacun, vingt et un logins en vérifient
une de plus.

VerifySecret relit m, t et p dans la chaîne stockée — propriété que
TestVerificationReadsTheCostFromTheStoredHash énonce déjà. Une empreinte écrite au
coût minimal se vérifie donc au coût minimal. HashSecret garde ses 64 MiB et
TestArgon2idRoundTrip continue de les épingler : aucun chemin de production ne
change
.

Mesuré sur le poste de développement, internal/web :

avant après
-race 29,8 s 5,6 s
sans race 21,3 s 2,9 s

Huit étapes en série qui ne se devaient rien

vet (33 s), puis -race (2 min 13), puis la passe sans cgo (51 s), puis les gardes.
Réparties en trois travaux qui tournent ensemble :

Travail Ce qu'il fait
race la passe -race, seule
test la passe sans cgo et les planchers de couverture
guards vet, frontières, dépendances, format

Le critère du découpage est écrit dans ci.yml, parce qu'il n'est pas esthétique :
une étape ne peut partir que si elle ne lit rien du travail qu'elle quitte. C'est
le cas des quatre gardes. Ce n'est pas le cas des planchers de couverture, qui lisent
le profil produit par la passe sans cgo — ils restent avec elle.

Aucune étape n'est perdue ni ajoutée. Le seul coût est un setup-go de plus par
travail, payé en parallèle et sur un cache chaud.

Ce que cette pull request mesure d'elle-même

Son propre run est la vérification : le mur attendu est d'environ 1 min 35 contre
3 min 55, et c'est race qui doit désormais plafonner.

…login

Les tests d'`internal/web` fabriquaient leurs empreintes avec `HashSecret`, donc
au coût d'un login sur l'i3 du poste : argon2id, 64 MiB, t=3, p=2. Trente-quatre
montages en écrivent deux chacun, vingt et un logins en vérifient une de plus.
Sous `-race`, où argon2 alloue ces 64 Mo dans un processus instrumenté, le paquet
mettait 59 s en CI — le plus lourd du dépôt, et à lui seul près de la moitié de la
passe `-race`.

Rien n'obligeait à payer ce prix : `VerifySecret` relit m, t et p DANS LA CHAÎNE
STOCKÉE, propriété que `TestVerificationReadsTheCostFromTheStoredHash` énonce déjà.
Une empreinte écrite au coût minimal se vérifie donc au coût minimal, sans qu'aucun
chemin de production change : `HashSecret` garde ses 64 MiB, et
`TestArgon2idRoundTrip` continue de les épingler.

Mesuré ici, `internal/web` :

    -race       29,8 s -> 5,6 s
    sans race   21,3 s -> 2,9 s

`go test ./... -short` reste vert.
Le travail « Tests et frontières » enchaînait huit étapes en série : 33 s de `go
vet`, 2 min 13 de passe `-race`, 51 s de passe sans cgo, puis les gardes. Trois
minutes cinquante et une, pendant que les trois autres travaux avaient fini depuis
plus de deux minutes et que des runners restaient inoccupés.

Ces étapes ne se devaient rien. Elles sont donc réparties en trois travaux qui
tournent ensemble :

    race    la passe -race, seule
    test    la passe sans cgo et les planchers de couverture
    guards  vet, frontières, dépendances, format

Le critère du découpage est écrit dans le fichier, parce qu'il n'est pas
esthétique : une étape ne peut partir que si elle ne lit rien du travail qu'elle
quitte. C'est le cas des quatre gardes. Ce n'est PAS le cas des planchers de
couverture, qui lisent le profil produit par la passe sans cgo — ils restent avec
elle.

Aucune étape n'est perdue ni ajoutée ; le seul coût est un `setup-go` de plus par
travail, payé en parallèle et sur un cache chaud. La note sur `-short` et
`skipUnderShort` remonte en tête de `jobs:`, puisqu'elle gouverne désormais deux
travaux.
@lostmind84
lostmind84 merged commit 792ae96 into main Aug 2, 2026
8 checks passed
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