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.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.2msLe 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.



