Increase maximum text word count and optimize line splitting function

This commit is contained in:
rabot
2026-10-07 16:42:17 +02:00
parent 875af6fe9e
commit 14c89b3963
15 changed files with 7148 additions and 27 deletions
+135
View File
@@ -697,3 +697,138 @@ chauffe incluse. L'empreinte reste **`1d53de903efd2b7c`**.
Les [100 mesures brutes](../resultats/mesures/comparaison_normalisation_meme_pc.csv) sont
conservées, ainsi que les [conditions et statistiques détaillées](../resultats/mesures/comparaison_normalisation_meme_pc.json),
qui identifient le commit de référence et les deux sources utilisées.
## Découpage en place dans le tampon du texte
Après la réorganisation du dépôt, le programme se trouve dans
`src/analyseur.c` et les commandes de validation sont `make check` et
`make profile`.
`decouper_lignes` reçoit maintenant un `char *` modifiable. Chaque saut
de ligne est remplacé par `\0`, et le tableau retourné contient des
pointeurs vers le début des lignes dans le tampon `texte`. Les allocations
et copies individuelles disparaissent ; le tableau de pointeurs conserve
son allocation initiale et ses agrandissements par `realloc`.
Les lignes restent valides tant que `texte` existe. La normalisation agit
directement sur ce tampon. À la fin du programme, on libère le tableau de
pointeurs, puis `texte`, sans appeler `free` sur chaque ligne.
Les lignes vides sont conservées. Seules les lignes terminées par `\n`
sont retournées, comme dans la version précédente ; le générateur produit
déjà un saut de ligne final. Le parcours reste en O(taille du texte), mais
il évite les allocations et les copies de son contenu.
Sur le corpus complet, cela supprime **21 746 allocations de lignes** et
autant de libérations. Le stockage de leurs copies représentait
**1 561 330 octets**, soit environ **1,49 Mio**, hors coût de l'allocateur.
Le profil est archivé dans [09_decoupage.txt](../resultats/profils/09_decoupage.txt).
La comparaison utilise le commit `875af6fe9eaee7a2a9a997c7fe4102d216a1b9fb`
comme référence avant modification. Les deux versions sont compilées avec
`-std=c11 -Wall -Wextra -Wpedantic -O0`, sans `-pg`, puis exécutées sur
**salle235-06**, CPU logique **0**, avec **GCC 16.2.1**.
Après cinq exécutions de chauffe par version, 50 mesures par version
sont réalisées en alternant l'ordre à chaque paire. Le temps réel inclut
le lancement du programme et ses écritures dans `build/`. Le temps CPU
est la somme des temps utilisateur et système du processus. Le pic RSS
est mesuré dans une série séparée avec `/usr/bin/time -f %M`, cinq fois
par version, sur le même CPU.
| Mesure | Avant : copies des lignes | Après : pointeurs dans le texte |
| --- | ---: | ---: |
| Allocations du contenu des lignes | 21 746 | 0 |
| Octets alloués pour le contenu des lignes | 1 561 330 | 0 |
| Temps réel médian | 84,36 ms | 79,60 ms |
| Temps CPU médian | 54,75 ms | 49,38 ms |
| Pic RSS médian | 6 688 Kio | 4 896 Kio |
Le gain médian est de **5,6 % en temps réel** et de **9,8 % en temps CPU**.
La nouvelle version est plus rapide dans 36 paires sur 50 en temps réel
et 39 sur 50 en temps CPU. Les temps fluctuent : la comparaison porte
sur cette série avant/après, et non sur les mesures historiques de la
normalisation. La baisse du pic RSS médian est de **1 792 Kio**.
Les [mesures de temps](../resultats/mesures/comparaison_decoupage_meme_pc.csv),
les [mesures de mémoire](../resultats/mesures/comparaison_decoupage_memoire.csv)
et les [conditions et statistiques](../resultats/mesures/comparaison_decoupage_meme_pc.json)
sont conservées. Le fichier de conditions contient aussi les empreintes
SHA-256 des sources avant et après modification.
Validation : `make check` et `make profile` passent sans avertissement de
compilation. Les 110 exécutions de comparaison, chauffe comprise, et les
10 mesures de mémoire produisent un rapport et une sortie console
identiques octet par octet à la référence. L'empreinte reste
**`1d53de903efd2b7c`**.
Des tests temporaires sous AddressSanitizer et UndefinedBehaviorSanitizer
ont comparé le découpage à l'ancienne fonction sur les textes vides, les
lignes vides, les suffixes sans saut de ligne, les zéros internes, les
fins de ligne CRLF, une ligne de 65 536 caractères, les seuils de capacité
jusqu'à 32 769 lignes et le corpus complet. Ils vérifient aussi que chaque
pointeur vise le tampon initial et que les lignes restent identiques
après normalisation. Le programme complet passe également avec ces outils,
sans double libération ni accès mémoire invalide.
Commandes utilisées pour cette étape à 250 000 mots, avant l'augmentation
du volume :
```bash
make check
make profile
cp build/profil/profil.txt resultats/profils/09_decoupage.txt
```
## Comparaison du découpage sur 10 millions de mots
Le paramètre `NB_MOTS_TEXTE` passe à **10 000 000**. Pour comparer le
découpage, ce changement est appliqué aussi à la version avant optimisation,
issue du commit `875af6fe9eaee7a2a9a997c7fe4102d216a1b9fb`. Les différences
entre les deux versions restent le découpage en place et la suppression
des libérations individuelles des lignes.
Les deux versions sont compilées avec
`-std=c11 -Wall -Wextra -Wpedantic -O0`, sur **salle235-06**, avec
**GCC 16.2.1**, puis exécutées sur le **CPU logique 0**. Deux mesures sans
`-pg` sont réalisées par version, dans l'ordre avant/après puis après/avant.
Une exécution profilée supplémentaire par version produit les nouveaux
profils.
| Mesure | Avant découpage en place | Après découpage en place |
| --- | ---: | ---: |
| Temps réels sans profiling | 2,042 s ; 1,993 s | 1,768 s ; 1,765 s |
| Temps réel moyen | 2,0175 s | 1,7664 s |
| Temps CPU moyen | 1,95 s | 1,72 s |
| Moyenne des pics RSS | 145 780 Kio | 72 054 Kio |
| Temps propre de `decouper_lignes` avec `-pg` | 0,28 s | 0,12 s |
| Temps total attribué par `gprof` | 1,65 s | 1,57 s |
Le gain observé sur les deux mesures sans instrumentation est de
**12,4 % en temps réel** et **11,8 % en temps CPU**. Le pic RSS moyen
baisse de **50,6 %**, d'environ **142,4 Mio à 70,4 Mio**. Les deux mesures
individuelles donnent une version après découpage plus rapide.
Les [nouveaux profils avant](../resultats/profils/10000000_mots/avant_decoupage.txt)
et [après](../resultats/profils/10000000_mots/apres_decoupage.txt) reposent
respectivement sur environ **165 et 157 échantillons attribués**, avec
une période de 0,01 s. Les anciennes captures à 250 000 mots n'en
contenaient que 3 et 7 : elles étaient trop courtes pour interpréter une
variation de quelques centièmes comme une régression. Les temps de
`gprof` restent des estimations ; le gain global est mesuré sans `-pg`.
Les [mesures brutes](../resultats/mesures/comparaison_decoupage_10000000.csv)
et les [conditions détaillées](../resultats/mesures/comparaison_decoupage_10000000.json)
identifient les sources, leurs empreintes SHA-256, le protocole et les profils.
Le nouveau corpus contient **10 000 000 mots**, **869 827 lignes** et
**6 098 mots distincts**. Le bigramme reste `me`, avec 696 057 occurrences
et `n` comme troisième lettre la plus fréquente. Les six exécutions
produisent des rapports et sorties console identiques avant/après.
L'empreinte de ce nouveau volume est **`b35be1258a9cb3f6`**. Le
[rapport de référence à 10 millions](../resultats/rapport_reference_10000000.txt)
est issu de la version avant découpage, puis vérifié avec la version
après découpage. Le [rapport historique à 250 000 mots](../resultats/rapport_reference.txt)
et son empreinte `1d53de903efd2b7c` sont conservés. `make check` utilise
désormais la référence à 10 millions de mots.