All news
ASCodeworksReleases

SYNX 3.8 est plus rapide partout, et tous les parseurs sont enfin d’accord

SYNX 3.8.0 ne change rien au langage. Ce qui change, c’est la vitesse à laquelle chaque implémentation le lit, jusqu’à 9,6 fois plus vite en TypeScript et 2 à 3,6 fois en Rust, et le fait qu’elles donnent désormais toutes la même réponse pour le même fichier.

by APERTURESyndicate · 17 octobre 2026

SYNX 3.8 est plus rapide partout, et tous les parseurs sont enfin d’accord

SYNX 3.8.0 est sorti, et si vous vous contentez d’écrire des fichiers de configuration, vous ne verrez rien de nouveau dans les fichiers eux-mêmes, parce que la grammaire n’a pas bougé d’un millimètre. Ce qui a bougé, c’est tout ce qu’il y a en dessous : le cœur en Rust, le paquet TypeScript, les bindings Python et Node et les sept portages natifs ont été mesurés face à 3.7.4 sur la même machine et les mêmes fichiers, puis reconstruits là où le temps partait réellement.

Combien plus rapide

La version courte, écrite dans le format lui-même :

# 3.7.4 -> 3.8.0, same machine, same files
rust
  config_2_5kb     38.6us -> 17.6us
  static_4mb       60.1ms -> 35.3ms
  active_1_2mb     81.0ms -> 22.5ms
typescript_node
  config_2_5kb     34.0us -> 20.4us
  active_1_2mb    297.5ms -> 31.1ms
python
  config_2_5kb     50.3us -> 17.6us
  synxl_100k      173.7ms -> 83.2ms

Le plus gros saut, c’est TypeScript sur les gros documents avec des marqueurs, et la raison est un peu gênante : chaque clé :calc repassait son expression sur toutes les autres clés du document, si bien que le travail grandissait avec le carré de la taille du fichier. En Rust, l’essentiel du gain vient de la mémoire. Avec l’allocateur système de Windows, une simple lecture passait près de la moitié de son temps à demander de la mémoire, et 3.8.0 en demande environ trois fois moins souvent sur les fichiers statiques et cinq fois moins souvent en mode actif. Le format binaire .synxb a eu droit au même traitement : les chaînes les plus fréquentes d’un document reçoivent maintenant les index les plus courts, les fichiers sont plus petits de 3 à 20 % en Rust et jusqu’à 40 % en TypeScript, et un même document donne désormais toujours les mêmes octets, ce que 3.7.4 ne garantissait pas.

Les parseurs n’étaient pas vraiment d’accord

Cette partie, on ne la cherchait pas. Pour vérifier que le code plus rapide donnait les mêmes résultats, nous avons donné les mêmes documents générés au hasard au cœur Rust et au paquet TypeScript en comparant ce qui en sortait, et 17 % des documents !active ont donné un résultat différent. Parfois TypeScript avait tort, parfois Rust, et parfois Rust se trompait différemment à chaque exécution : il parcourait les objets dans l’ordre d’une table de hachage, si bien que l’exemple tax:calc / total:calc tiré tel quel de la spécification échouait avec CALC_ERR environ une fois sur deux.

Et une fois qu’on a commencé à chercher, on en a trouvé d’autres. Les marqueurs à l’intérieur des éléments de liste n’étaient jamais appliqués en Rust. Synx.stringify et .synxb modifiaient les données au retour : "007" revenait sous la forme du nombre 7, les blocs de code |+ perdaient leur indentation, et 1 777 documents aléatoires sur 3 000 ne survivaient pas à l’aller-retour. Quelques documents pouvaient même faire tomber tout le processus : :clamp:nan:5 faisait paniquer Rust, et un fichier qui s’incluait lui-même faisait déborder la pile. Ces 55 défauts sont tous corrigés, et sur le code final le cœur Rust et TypeScript sont d’accord sur chacun des 70 000 documents générés.

Sept portages, tous en 3.8.0

SYNX a aussi des parseurs natifs pour Go, Java, .NET, Dart, C++, Swift et Godot, qui avaient pris quelques versions de retard. Ils sont tous en 3.8.0 maintenant, vérifiés de la même manière face au cœur Rust sur des milliers de documents générés chacun, et il ne reste aucune différence. Certains ont beaucoup plus changé que d’autres : les portages C++ et Swift mettaient 88 et 47 secondes pour un document actif de 1,2 Mo et mettent maintenant 33 et 95 millisecondes, et l’addon Godot ne compilait même pas sous Godot 4.7 avant cette version.

Mettre à jour

Vos fichiers .synx n’ont pas besoin de changer. Les paquets sont @aperturesyndicate/synx-format sur npm, synx-core sur crates.io et synx-format sur PyPI, et les portages arrivent par leurs registres habituels. Si vous utilisez synx-core directement depuis Rust, les objets sont maintenant une IndexMap ordonnée au lieu d’une HashMap : le code qui construit lui-même une HashMap pour l’envelopper aura besoin d’un .collect(), tandis que tout ce qui lit via get et l’itération compile comme avant.

Il reste une chose que le format ne sait pas exprimer : une liste à l’intérieur d’un élément de liste, suivie d’un autre élément, ne survit pas à l’écriture puis à la relecture, parce que SYNX ne garde qu’une liste ouverte à la fois. C’est prévu pour la 4.0, avec les chaînes compactes, qui sur une copie de laboratoire du cœur ont encore accéléré la lecture de 1,2 à 1,5 fois.

Toutes les modifications, avec les chiffres, sont dans le journal des modifications et dans la version 3.8.0 sur GitHub.

Other stories

All stories
SYNX 3.8 est plus rapide partout, et tous les parseurs sont enfin d’accord | APERTURESyndicate