veilletech.fr
13 oct. Feed du jour
#08 PERFORMANCE Article

fastsimdjson : 66 Go/s de JSON, en Python

Ce qui coûtait, ce n'était pas de lire le JSON. C'était d'en faire des objets.

Daniel Lemire mesure fastsimdjson, une liaison Python de simdjson, sur 7,6 Go d'événements GitHub : 66 Go/s avec 64 fils sur Python sans GIL, contre 3 Go/s pour le module json et 25 Go/s pour msgspec. Le gain vient du mode paresseux, qui ne crée des objets Python que pour les champs lus. Banc d'essai publié ; une seule machine à 64 cœurs.

3 min de lectureavancévidéo 1:18
Partager
Sommaire7 sections
  1. Ce qui se passe
  2. Le test
  3. Les résultats
  4. Pourquoi
  5. Limites
  6. Comment s'y prendre
  7. À retenir

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.

Python
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.