Ce qui se passe
Daniel Lemire publie une mesure de fastsimdjson, une liaison Python de
simdjson (« notre liaison », écrit-il), dans sa version 0.6.0 sur PyPI. Sur un
serveur à 64 cœurs, avec Python 3.14 sans verrou global
(python3.14t), elle analyse du JSON à 66 Go/s dans un seul processus.
Le test
Huit heures d'événements publics de GitHub (GH Archive), du 13 mars 2024 : 7,6 Go décompressés, 2,2 millions d'événements au format NDJSON, soit 3,4 ko en moyenne chacun, dont il ne faut que quelques champs. La question : quels langages reçoivent le plus de nouvelles pull requests ? Réponse sur ces huit heures : 65 269 ouvertes, dont 11 565 vers du TypeScript, 7 778 vers du JavaScript, 7 057 vers du Python et 4 668 vers du Java.
Chaque méthode produit les mêmes comptes, vérifiés. Meilleur de sept passages, les données sont décompressées avant le chronomètre ; machine : deux Xeon Gold 6548N, orjson 3.13.0, msgspec 0.22.0.
Les résultats
Sur un cœur :
| Méthode | Go/s |
|---|---|
json (bibliothèque standard) |
0,18 |
| orjson | 0,42 |
fastsimdjson map_many |
0,63 |
| msgspec (structures typées) | 1,29 |
fastsimdjson map_many paresseux |
2,13 |
La bibliothèque standard met 42 secondes pour les huit heures, fastsimdjson paresseux 3,6.
Avec 64 fils dans un processus :
| Méthode | Go/s |
|---|---|
json, 64 fils |
3,17 |
| msgspec, 64 fils | 24,6 |
fastsimdjson map_many, 64 fils |
29,8 |
fastsimdjson map_many paresseux, 64 fils |
65,7 |
Soit 7,6 Go en environ 0,12 seconde, 31 fois plus vite qu'avec un seul cœur.
Pourquoi
Les méthodes qui matérialisent tout (json, orjson, fastsimdjson sans mode
paresseux) passent l'essentiel du temps à créer des objets Python qu'on jette
aussitôt. En mode paresseux, la fonction reçoit une vue de l'événement :
il est analysé, mais des objets Python ne sont créés que pour les valeurs
qu'on lit. L'idée vient de Tyler Kennedy, dans la liaison pysimdjson. msgspec
fait presque la même économie, à condition de déclarer le schéma à l'avance :
Lemire lui a donné cet avantage.
Chaque fil garde ses propres compteurs, créés au premier événement vu et ajoutés à une liste. Rien n'est partagé, donc aucun fil n'attend ; le fil principal fusionne les compteurs à la fin, ce qui est négligeable.
import fastsimdjson
fastsimdjson.map_many(un_evenement, data, format="lines", threads=64, lazy=True)Limites
Une seule machine, très large (64 cœurs), un seul auteur, et un cas favorable (quelques champs lus dans de gros objets). La bibliothèque vient d'atteindre la 0.6.0. L'accélération dépend du Python sans GIL pour les 64 fils ; sur un seul cœur, le gain reste d'environ 12 fois sur la bibliothèque standard.
Comment s'y prendre
Si vous lisez peu de champs dans de gros fichiers NDJSON, comparez
fastsimdjson (mode paresseux) et msgspec sur vos propres données, avec le banc
d'essai de l'auteur (dépôt lemire/Code-used-on-Daniel-Lemire-s-blog, dossier
2026/10/pyjson). Si vous lisez presque tout le document, le mode paresseux
devrait perdre l'essentiel de son avantage, puisqu'il tient à ne créer que les
objets lus : c'est une déduction, pas une mesure de l'auteur. Mesurez avant de
migrer.
Source : Parsing JSON at tens of gigabytes per second… in Python, Daniel Lemire, 12 octobre 2026.