Le projet Julia a publié la version 1.13 de son langage de programmation. Cette version met fortement l'accent sur la réduction de la latence, l'un des points faibles de longue date de Julia. Selon l'annonce, la précompilation des paquets prend désormais environ 30 % moins de temps que dans Julia 1.12, et 10 à 20 % moins de temps que la version 1.10 à support à long terme, selon la machine, tandis que le démarrage lui-même est environ 20 % plus rapide que dans la version précédente. Un autre point fort majeur est une modification apportée au ramasse-miettes. Le coût d’un ramassage complet évolue désormais en fonction du tas effectivement créé par un programme plutôt que de la quantité de code chargé.Julia est un langage de programmation de haut niveau, performant et dynamique conçu pour le calcul scientifique et les applications de calcul numérique. Sa syntaxe est familière aux utilisateurs d'autres environnements de développement tels que MATLAB, R, Scilab, et Python. Julia est connue pour sa vitesse et ses capacités avancées en termes de calcul parallèle et de gestion de données volumineuses. Julia combine les avantages des langages compilés (tels que C et Fortran) avec la flexibilité des langages dynamiques.
Bien qu'étant un langage généraliste dans sa conception, Julia est majoritairement utilisé dans le monde scientifique. On le retrouve notamment dans des domaines tels que la science des données, la modélisation numérique, la statistique, l'apprentissage automatique ou encore la biologie et la climatologie. Les utilisateurs du langage sont en majorité des ingénieurs, des chercheurs ou des étudiants, qui l'utilisent pour faire de la recherche scientifique ou comme un passe-temps. Certains utilisateurs trouvent dans Julia un langage avec une syntaxe simple comme Python tout en ayant des performances élevées.
Le projet Julia a publié la version 1.13 de son langage de programmation. Cette version met fortement l'accent sur la réduction de la latence, l'un des points faibles de longue date de Julia. Selon l'annonce, la précompilation des paquets prend désormais environ 30 % moins de temps que dans Julia 1.12, et 10 à 20 % moins de temps que la version 1.10 à support à long terme, selon la machine, tandis que le démarrage lui-même est environ 20 % plus rapide que dans la version précédente. Afin de limiter les régressions futures, le projet a également intégré la surveillance de la latence dans son propre pipeline de développement : des tâches d’intégration continue dédiées au temps de premier tracé/exécution (TTFX) s’exécutent désormais sur les pull requests et à chaque commit vers la branche master, les résultats étant suivis publiquement.
Un autre point fort majeur est une modification apportée au ramasse-miettes. Les objets présents dans l’image système et les images de paquets sont désormais chargés en tant qu’objets marqués de manière permanente et ignorés par la phase de marquage du ramasse-miettes, les rares mutations qui se produisent étant suivies séparément. En conséquence, le coût d’un ramassage complet évolue désormais en fonction du tas effectivement créé par un programme plutôt que de la quantité de code chargé. La différence est frappante au vu des chiffres présentés dans l’article de blog : le temps d’exécution d’un GC.gc() complet dans une nouvelle session était d’environ 0,035 seconde dans Julia 1.12, contre environ 0,0005 seconde dans la version 1.13, soit une réduction de près de 70 fois.
Au-delà des performances, cette version apporte toute une série de fonctionnalités pratiques destinées aux développeurs. Une nouvelle macro publique @__FUNCTION__ vient s’ajouter à @__MODULE__ et @__FILE__ pour référencer la fonction contenante la plus interne, y compris les fonctions anonymes. En coulisses, l’algorithme de hachage par défaut pour les chaînes de caractères et de nombreux types numériques a été remplacé : MurmurHash3 a cédé la place à RapidhashNano, un hachage en continu écrit en Julia pur qui, selon les développeurs, est nettement plus rapide et plus facile à maintenir.
Le débogage bénéficie également d’améliorations : un nouvel indicateur de ligne de commande --trace-eval affiche la progression de l’évaluation au niveau supérieur afin de faciliter la détection des blocages dans les scripts et les suites de tests ; il est activé automatiquement lorsque la journalisation de débogage est activée pour les exécutions en intégration continue (CI). Enfin, l’outil expérimental de « trimming » juliac est désormais disponible sous la forme d’un véritable paquet appelé JuliaC.jl, prenant en charge le « trimming » d’un plus grand nombre de constructions telles que les finaliseurs, @cfunction et mapreduce, ce qui constitue une avancée pour la production de binaires Julia compilés plus légers.
Voici quelques points forts de Julia 1.13 :
Améliorations de la latence (TTFX)
Julia 1.13 met environ 30 % moins de temps à précompiler les paquets que la version 1.12, et environ 10 à 20 % moins de temps que la version 1.10 (LTS), selon la machine.
Le « Time To First X » (TTFX), c'est-à-dire le temps écoulé entre le démarrage de Julia et l'obtention d'un premier résultat, se compose de trois coûts principaux : la précompilation des paquets, leur chargement et l'exécution du code. Grâce aux workflows proposés par la communauté sur Julia-TTFX-Snippets, nous avons commencé à mesurer ces coûts de manière plus systématique à partir d’exemples concrets et à optimiser Julia en fonction de ceux-ci.
Le graphique ci-dessous présente la moyenne géométrique des 39 workflows actuellement proposés, sur deux machines. La précompilation correspond au meilleur temps sur deux exécutions ; les temps de chargement et d’exécution correspondent au meilleur temps sur trois exécutions.
Ce suivi fait désormais partie intégrante du processus de développement de Julia : de nouvelles tâches de CI TTFX sont exécutées sur les pull requests pertinentes et à chaque commit sur la branche master, et les résultats sont suivis sur perf.julialang.org/ttfx. Ce suivi a été mis en place le 7 septembre 2026 ; les mesures effectuées avant cette date étaient ponctuelles.
Le démarrage de Julia 1.13 est également environ 20 % plus rapide que celui de la version 1.12.
| Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | % hyperfine --warmup 3 --runs 20 -N \ --command-name "julia 1.12" "julia +1.12 --startup-file=no -e ''" \ --command-name "julia 1.13" "julia +1.13 --startup-file=no -e ''" Benchmark 1: julia 1.12 Time (mean ± σ): 69.1 ms ± 1.0 ms [User: 50.1 ms, System: 18.1 ms] Range (min … max): 68.0 ms … 72.6 ms 20 runs Benchmark 2: julia 1.13 Time (mean ± σ): 56.7 ms ± 0.5 ms [User: 49.1 ms, System: 18.9 ms] Range (min … max): 56.0 ms … 58.1 ms 20 runs Summary julia 1.13 ran 1.22 ± 0.02 times faster than julia 1.12 |
Améliorations du REPL
Mise en évidence de la syntaxe
Le REPL de Julia dispose désormais d’une mise en évidence de la syntaxe (sans avoir à charger un paquet externe tel que OhMyREPL.jl) :
Par défaut, le jeu de couleurs est assez sobre, mais il est facile à personnaliser (voir la documentation du REPL). À titre d’exemple, voici le même code en utilisant le jeu de couleurs Monokai :
Nouvelle recherche dans l’historique de type fzf
La recherche dans l’historique (accessible par défaut via Ctrl-R) a été repensée et fonctionne désormais de manière similaire à l’outil de recherche floue en ligne de commande fzf :
Entre autres, la nouvelle recherche dans l’historique prend en charge :
- La recherche floue dans l’historique.
- L’affichage du mode REPL utilisé pour la commande.
- La sélection de plusieurs résultats de recherche à placer dans le tampon de l’invite.
- La mise en évidence de la syntaxe du code, en accord avec celle du REPL lui-même.
Accédez à la recherche dans l’historique et tapez ? pour consulter l’aide complète.
Collage entre crochets sous Windows
Le collage entre crochets permet à une application s’exécutant dans un terminal de savoir quand du texte est collé (par opposition à une simple saisie). Cela permet un traitement plus efficace et plus précis du texte collé. Cette fonctionnalité est disponible depuis longtemps sous Linux et macOS, mais elle est désormais enfin disponible sous Windows.
@__FUNCTION__
À l’instar des macros existantes @__MODULE__ et @__FILE__, la nouvelle macro @__FUNCTION__ fait référence à la fonction contenante la plus interne, même si cette fonction est anonyme. Cela devrait fonctionner dans tous les types de fonctions et constitue une API publique, contrairement à la variable interne #self#.
| Code : | Sélectionner tout |
1 2 3 4 | julia> fact = n -> n <= 1 ? 1 : n * @__FUNCTION__()(n - 1); julia> fact(5) 120 |
Modifications apportées au hachage
La fonction de hachage a été remplacée. L’algorithme de hachage par octet est désormais RapidhashNano. Ce hachage est utilisé par défaut pour AbstractString et de nombreux types numériques tels que BigInt, Rational, ainsi que les valeurs Real ou Integer de grande taille. Il est désormais également beaucoup plus facile pour les types personnalisés d’adopter les implémentations génériques sans avoir à se convertir au préalable en un type pris en charge (comme String). Ce changement offre plusieurs avantages par rapport à l’implémentation préexistante basée sur MurmurHash3. Il offre des performances nettement supérieures, s’agit d’un hachage en continu qui ne nécessite donc plus de connaître la longueur de l’entrée à l’avance, et a été réécrit en Julia pur (au lieu de C) pour une meilleure lisibilité et maintenabilité.
Pour illustrer l’amélioration des performances sur les longues chaînes de caractères :
| Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | using BenchmarkTools, Downloads io = IOBuffer() Downloads.download("https://www.gutenberg.org/cache/epub/1080/pg1080.txt", io) s = String(take!(io)); # 1.12 @btime hash($s) 8.555 μs (0 allocations: 0 bytes) 0x5fbd2717019846ea # 1.13 @btime hash($s) 1.742 μs (0 allocations: 0 bytes) 0x718308e795047519 |
Et une démonstration de l’utilisation d’une solution de repli plus rapide :
| Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | struct MyString <: AbstractString s::String end m = MyString(s); # 1.12 Base.iterate(m::MyString) = iterate(m.s) Base.iterate(m::MyString, i::Integer) = iterate(m.s, i) @btime hash($m) 204.583 μs (21 allocations: 107.02 KiB) 0x5fbd2717019846ea # 1.13 Base.codeunit(m::MyString) = codeunit(m.s) Base.codeunits(m::MyString) = codeunits(m.s) @btime hash($m) 1.750 μs (0 allocations: 0 bytes) 0x718308e795047519 |
Le hachage des petites données à largeur fixe a également été modifié. L’étape finale de mélange est désormais une construction XMX à un seul tour avec des constantes soigneusement ajustées, et l’étape de mélange produit désormais correctement un effet d’avalanche lors de la composition d’appels de hachage ; auparavant, l’étape de mélange se simplifiait toujours en une fonction linéaire à chaque profondeur de composition. Cette modification de l’étape de mélange introduit une dépendance aux données (et donc potentiellement une baisse de performances) lors du hachage séquentiel d’éléments dans une boucle serrée, par exemple foldr(hash, collection), mais l’algorithme de hachage d’AbstractArray a été partiellement déroulé pour les tailles petites à moyennes, en maintenant plusieurs accumulateurs de hachage en parallèle, et sera bien plus rapide pour la plupart des longueurs.
Quelques rappels importants : la fonction hash reste non cryptographique. De plus, la graine par défaut a changé. Les méthodes de hachage personnalisées doivent toujours accepter la graine en tant qu’argument, comme hash(x::MyType, h::UInt), et ne jamais fournir de valeur par défaut, comme hash(x::MyType, h::UInt=0), car la graine correcte est déterminée par l’appelant.
Accélération du ramasse-miettes (GC) en ignorant les objets d’image lors du marquage
Chaque session Julia commence avec un grand nombre d’objets chargés à partir de l’image système, et chaque paquet chargé apporte sa propre image de paquet contenant encore davantage d’objets : tables de méthodes, informations de type, code compilé, constantes, etc. Ces objets ne sont jamais libérés et sont rarement modifiés ; pourtant, jusqu’à présent, un ramasse-miettes complet les parcourait tous pour les marquer comme accessibles, au même titre que...
La fin de cet article est réservée aux abonnés. Soutenez le Club Developpez.com en prenant un abonnement pour que nous puissions continuer à vous proposer des publications.