Optimisation des performances en mémorisant la longueur des mots et en supprimant les parcours redondants

This commit is contained in:
rabot
2026-10-07 12:12:56 +02:00
parent 57aaec48d0
commit 1c4405c75e
5 changed files with 265 additions and 18 deletions
+86
View File
@@ -280,3 +280,89 @@ mkdir -p out/apres_hachage
gcc -O0 -pg analyseur.c -o out/apres_hachage/analyseur
(cd out/apres_hachage && ./analyseur && gprof -b ./analyseur gmon.out > ../profil_apres_hachage.txt)
```
## Longueurs mémorisées et suppression des parcours répétés
Le champ `taille` de `Entree` mémorise la longueur du mot à son insertion.
La valeur vient directement de `k`, déjà calculé dans `compter_mots_ligne` :
aucun parcours supplémentaire n'est nécessaire. La moyenne et la variance
lisent désormais ce champ. Le tri déplace l'entrée entière, donc la longueur
reste associée au bon mot. Pour un mot tronqué, la taille enregistrée est
celle du mot conservé, soit au maximum 31 caractères.
Deux autres changements éliminent les recalculs sur les chaînes longues :
- `normaliser_ligne` s'arrête directement sur `ligne[i] == '\0'`. Le parcours
d'une ligne de L caractères passe de O(L²) à O(L).
- `ajouter` reçoit une position de fin, qu'il avance pendant la copie des
caractères ajoutés. Cette position est conservée lors de la construction
du rapport et réinitialisée pour chaque mot du vocabulaire. Le préfixe
déjà construit n'est plus parcouru à chaque ajout.
La fonction `longueur`, devenue inutilisée, a été supprimée.
Le champ supplémentaire fait passer `sizeof(Entree)` de 36 à 40 octets sur
cette machine : le tableau alloué pour 20 000 entrées prend 80 000 octets
supplémentaires, soit environ 78 Kio.
Profil enregistré dans [out/profil_apres_longueurs.txt](out/profil_apres_longueurs.txt).
La version précédente, avec la table de hachage, est décrite dans
`out/profil_apres_hachage.txt`.
| Mesure | Avant | Après |
| --- | ---: | ---: |
| Appels à `longueur()` depuis les statistiques | 11 732 | 0 |
| Appels à `longueur()` depuis `normaliser_ligne` | 1 561 330 | 0 |
| Appels à `longueur()` depuis `ajouter` | 26 801 | 0 |
| Appels à `longueur()` au total | 1 599 863 | 0 |
| Temps réel médian sans profiling (`gcc -O0`, 5 exécutions par version) | 0,832 s | 0,362 s |
Le temps total baisse de 56,5 %, soit une accélération d'environ 2,30.
Cette mesure porte sur l'ensemble des trois changements, et ne doit pas
être attribuée uniquement au stockage de la longueur des mots.
Les cinq mesures, réalisées en alternant les deux versions sur la même
machine, sont respectivement : 0,835 / 0,838 / 0,830 / 0,832 / 0,829 s
avant, et 0,362 / 0,369 / 0,366 / 0,362 / 0,361 s après.
Validation : compilation sans avertissement avec `-Wall -Wextra -Wpedantic`,
rapport et sortie console identiques octet par octet sur les dix exécutions,
avec `-pg` et sous AddressSanitizer et UndefinedBehaviorSanitizer.
L'empreinte reste **`1d53de903efd2b7c`**, la moyenne `6.712` et l'écart-type
`1.873`. Des tests temporaires ont également vérifié les ajouts vides et
successifs jusqu'à la limite d'un tampon, la normalisation, les longueurs
avant/après tri, les statistiques, le rapport vide et les mots tronqués.
Commandes pour reproduire ce profil :
```bash
mkdir -p out/apres_longueurs
gcc -O0 -pg analyseur.c -o out/apres_longueurs/analyseur
(cd out/apres_longueurs && ./analyseur && gprof -b ./analyseur gmon.out > ../profil_apres_longueurs.txt)
```
```bash
[rabot@salle235-06 out]$ time ./analyseur
Lignes analysées : 21746
Mots au total : 250000
Mots distincts : 5866
Longueur moyenne : 6.712 (écart-type 1.873)
Bigramme le + courant : "me" (17607 fois, souvent suivi de 'n')
Top 10 :
1. rane 287
2. fasi 241
3. tata 219
4. mopo 214
5. cofi 180
6. vesi 179
7. laganomo 177
8. boto 172
9. nopebo 169
10. rotion 165
Empreinte du rapport : 1d53de903efd2b7c
real 0m0.751s
user 0m0.703s
sys 0m0.004s
```