1 points par GN⁺ 2023-12-26 | 1 commentaires | Partager sur WhatsApp
  • YJIT améliore fortement les performances et l’utilisation mémoire par rapport à Ruby 3.2, et devient plus de 3 fois plus rapide que l’interpréteur sur Optcarrot
  • Le Code GC de YJIT est désactivé par défaut, et --yjit-exec-mem-size fonctionne comme une limite stricte qui arrête la compilation de nouveau code
  • L’ajout de RubyVM::YJIT.enable permet d’activer YJIT à l’exécution sans modifier les arguments de ligne de commande ni les variables d’environnement
  • Le parseur Prism est ajouté comme gem par défaut, et les API Prism.parse(source), Prism.parse_comments(source), Prism.parse_success?(source) peuvent être utilisées
  • Il est possible d’expérimenter le compilateur Prism avec ruby --parser=prism ou RUBYOPT="--parser=prism", mais ce flag est réservé au débogage
  • Le générateur de parseur passe de Bison à Lrama, et le parseur interne de Lrama est remplacé par un parseur LR généré par Racc pour améliorer la maintenabilité
  • Le compilateur JIT pure-Ruby RJIT remplace MJIT, mais ne prend en charge que l’architecture x86-64 sur Unix et reste limité à un usage expérimental
  • Le scheduler de threads M:N est introduit : N threads natifs gèrent M threads Ruby, mais comme cela peut casser la compatibilité avec les extensions C, il est désactivé par défaut sur le Ractor principal
  • L’utilisation de it appelé sans argument dans un bloc sans paramètre ordinaire est dépréciée ; dans Ruby 3.4, il référencera le premier paramètre du bloc
  • Regexp::new n’accepte plus qu’un maximum de 2 arguments au lieu de l’appel à 3 arguments déprécié dans Ruby 3.2
  • ext/readline est retiré, et dépendra désormais de reline, une implémentation pure Ruby compatible avec l’API de ext/readline
  • Si ext/readline est nécessaire, il peut être installé depuis rubygems.org avec gem install readline-ext, sans qu’il soit désormais nécessaire d’installer des bibliothèques comme libreadline ou libedit
  • RubyGems et Bundler affichent un avertissement si certains gems sont require sans être ajoutés au Gemfile ou au gemspec ; ces gems deviendront des bundled gems dans de futures versions de Ruby
  • Lors de l’utilisation du gem bootsnap, cet avertissement est supprimé ; en raison des limitations de cette version, il est recommandé d’exécuter l’application au moins une fois avec la variable d’environnement DISABLE_BOOTSNAP=1
  • prism 0.19.0 est ajouté comme gem par défaut, et racc 1.7.3 passe de default gem à bundled gem

1 commentaires

 
GN⁺ 2023-12-26
Avis sur Hacker News
  • Avec Ruby 3.3, je considère que Ruby fait un grand retour. Ce langage, qui se concentre sur le bonheur des développeurs mais était moqué pour sa lenteur, n’est désormais plus lent
    YJIT est une technologie impressionnante, et avec les shapes d’objets ainsi que diverses optimisations du garbage collection, Ruby devient assez rapide. De grands utilisateurs de Ruby comme Shopify ont aussi activé YJIT en production sur des préversions de 3.3 et rapportent des gains de performance à deux chiffres en pourcentage
    Personnellement, Ruby et son avenir m’enthousiasment vraiment, et j’ai envie de travailler avec Ruby 3.3 pour l’appliquer aux sites en production de mes clients
    https://railsatscale.com/2023-09-18-ruby-3-3-s-yjit-runs-sho...

    • Je ne sais pas si une légère amélioration des performances fera choisir Ruby à nouveau, mais c’est agréable de voir une progression incrémentale. Se préoccuper excessivement des performances relève presque toujours de l’optimisation prématurée, et Ruby a jusqu’ici été suffisamment rapide pour ce qu’on lui demandait
      Je l’ai aussi utilisé comme code de liaison entre un stockage d’enregistrements DNS basé sur Redis et PowerDNS ; toute la pile traitait 500 millions de requêtes par mois sur 14 petits VPS sans même se faire remarquer dans htop. Je n’ai pas utilisé PowerDNS pour des raisons de performance, mais parce qu’implémenter soi-même des choses comme la crypto, HTTP ou DNS exposés à l’Internet public est généralement une mauvaise idée
      L’ironie du Web actuel, c’est qu’une webapp faite avec du Ruby « lent » et du rendu serveur charge en réalité les pages plus vite qu’une base de données à cohérence finale réellement lente et qu’une grosse webapp frontend obèse. Sur le Web moderne, on voit trop souvent des spinners de chargement même pour des actions triviales
    • Le langage Ruby lui-même peut être rapide, mais tout l’écosystème est douloureusement lent. Quand on construit avec Rails un serveur qui renvoie 1 Mo de JSON par requête après des requêtes en base de données et des appels à d’autres services, on obtenait environ 100 requêtes par seconde ; en réécrivant le même service en Go, il traitait 100 000 requêtes par seconde
    • Je me demandais si « gain de performance à deux chiffres » voulait dire 10 % plus rapide, ou 10 fois plus rapide
      En cliquant sur le lien, il s’agissait d’une amélioration de l’ordre de 10 %. Cela ne changera probablement pas beaucoup la perception selon laquelle Ruby est environ 50 à 200 fois plus lent que des langages « rapides » comme Rust, Java, Go ou C++
    • Un domaine où Ruby pourrait améliorer l’expérience développeur est une meilleure expérience de débogage. Peut-être parce que je suis trop habitué à Chrome DevTools, mais la dernière fois que j’ai débogué du code Ruby avec beaucoup de métaprogrammation, comprendre ce qui se passait a été pénible
    • En entendant « à deux chiffres », je m’attendais à 50 % ou 80 %, mais en regardant le lien, c’était 13 à 15 %
  • Ruby 3.3 me semble être l’une des versions de Ruby les plus importantes et les plus riches en fonctionnalités de ces dix dernières années. Je ne pensais pas qu’ils sortiraient un JIT prêt pour la production avant Python, et il y a aussi Prism, Lrama et IRB
    En revanche, ce qui n’est pas assez abordé, ce sont Ractor, le planificateur de threads M:N, Fiber et Async. J’aimerais notamment savoir si, dans le contexte de Rails, des gens utilisent ces fonctionnalités en production, et avoir leurs avis

    • Il était tout à fait prévisible que Ruby sorte un JIT prêt pour la production avant Python. Ruby n’avait pas une énorme communauté de calcul scientifique dépendante de chaque détail d’implémentation de l’interpréteur hôte
    • Je me demande si Ruby 3.3 est vraiment une version si importante. Je ne vois pas ce qui la rend aussi significative
      Cela dit, Ractor mériterait davantage d’attention. C’est une fonctionnalité énorme
    • Je ne comprends vraiment pas pourquoi il n’existe pas une file de tâches unique couvrant à la fois Ruby et Python. Je comprends qu’à un moment donné, les gens ont commencé à échanger des informations via des microservices basés sur HTTP, mais au final, une simple file de tâches avec un format de stockage partagé entre les deux langages serait une meilleure façon de connecter des systèmes Ruby/Rails à des stacks de machine learning
      Il doit probablement y avoir des milliers de solutions privées sur mesure basées sur RabbitMQ ou Redis à l’intérieur des entreprises
  • Chaque année à Noël, comme une horloge, Ruby Lang publie une nouvelle version

  • Disponible sur Heroku : https://devcenter.heroku.com/changelog-items/2772

  • Ça a l’air bien. Le nouvel IRB est un interpréteur Ruby interactif avec une meilleure autocomplétion et un meilleur débogage. La plupart des changements de Ruby 3.3 semblent aller dans le sens d’une amélioration des outils développeur
    L’API du langage reste globalement cohérente avec les versions précédentes. J’ai rédigé un guide de mise à jour vers Ruby 3.3 avec des notes pour plusieurs gestionnaires de versions : https://mac.install.guide/ruby/update.html
    Je me demande toutefois quel gestionnaire de versions recommander. Auparavant, je recommandais asdf, frum et chruby

    • Je n’ai pas de problème particulier avec rbenv ou asdf. J’utilise les deux, en local et en production
  • La résolution de noms comme Socket.getaddrinfo peut désormais être interrompue, et il paraît qu’à chaque fois qu’une résolution de nom est nécessaire, un worker pthread est créé pour exécuter getaddrinfo(3) dedans
    Je me demande si les runtimes d’autres langages font quelque chose de similaire. Créer un thread semble très lourd, mais ce n’est peut-être pas un gros problème en pratique. D’après leurs propres benchmarks, le surcoût est faible, mais pas nul
    10000.times { Addrinfo.getaddrinfo("www.ruby-lang.org";, 80) } prenait 2,3 s avant le patch et 3,0 s après ; 100.times { URI.open("https://www.ruby-lang.org";).read } prenait 3,36 s avant le patch et 3,40 s après

    • Je me demande si c’est parce que toutes les opérations d’entrée/sortie de la bibliothèque standard doivent prendre en charge async/fiber
      J’ai l’impression que, plutôt que de réimplémenter les mêmes opérations avec une « couleur » async comme en Python, tout a été déplacé vers l’asynchrone par défaut, mais je ne sais pas si c’est exact
    • Je me dis qu’une fiber serait plus légère que de créer un nouveau thread
  • Si je connais déjà Python et NodeJS, je me demande si Ruby vaut la peine d’être appris. Ruby a l’air intéressant, mais aussi difficile

    • Ruby est, en gros, une sorte de Python moins populaire mais plus élégant. C’est un langage généraliste solide, particulièrement adapté à des tâches comme les scripts shell ou le nettoyage de données.
      Si vous maîtrisez Node et Python, il devrait être assez facile à apprendre. L’inconvénient, c’est que si vous connaissez déjà ces langages, il ne vous apportera rien de fondamentalement nouveau. Son avantage est surtout esthétique : Ruby offre et encourage une façon vraiment belle d’exprimer le code, et c’est agréable à découvrir.
    • Je trouve que Ruby est bien meilleur que Python ou Node pour les tâches de type scripting shell et la programmation interactive/exploratoire liée au système. L’utiliser comme un « meilleur bash » ou un « meilleur Perl » vaut largement le coup.
      Je travaille surtout dans des codebases TypeScript, mais quand je manipule des données de logs, du texte semi-structuré ou que je fais des réécritures basées sur des expressions régulières dans plusieurs fichiers, je ressors souvent Ruby. Ruby est très amusant, probablement le langage le plus amusant parmi ceux que j’ai utilisés régulièrement, et c’est une récompense en soi.
    • Tout dépend de ce que vous voulez en retirer. Le plus intéressant, c’est que Ruby ressemble beaucoup à Python sur plusieurs aspects, tout en étant en même temps assez différent.
      Le plus grand exemple est que Ruby aime vraiment les blocs. On en trouve partout dans la bibliothèque standard, il y a beaucoup de sucre syntaxique, et d’innombrables DSL construits autour des blocs. Les fonctionnalités fonctionnelles standard sont aussi présentes depuis longtemps dans la bibliothèque standard, ce qui permet d’écrire dans un style fonctionnel de façon fluide et lisible.
      Techniquement, la plupart de ces choses sont aussi possibles en Python, mais elles paraissent beaucoup plus maladroites à écrire et à lire. Python a bien des lambdas, mais on a l’impression qu’il ne les apprécie guère au-delà des usages triviaux ; à la place, les fonctions y sont des valeurs de première classe partout.
    • Pour obtenir des pistes d’amélioration du code pendant l’apprentissage, Rubocop est un bon outil. C’est à la fois un excellent linter et un bon professeur.
    • Il y a un peu plus de dix ans, vers 2011-2013, j’ai un peu utilisé Ruby — plus précisément le Ruby de Rails. À l’époque, on sentait encore l’inertie de RoR, apparu en 2005 et devenu très populaire en 2007-2009.
      Les gens sensibles aux technologies récentes passaient à un développement orienté API basé sur node.js et AngularJS, bien plus rapide que ce qui se faisait avec RoR. En 2013, la façon standard de faire avec RoR restait monolithique, et il avait mal pris le virage du nouveau paradigme de séparation front-end/back-end, ce qui le faisait paraître vieillissant.
      Si je parle longuement du framework construit avec Ruby plutôt que de Ruby lui-même, c’est parce qu’aujourd’hui encore, j’ai l’impression que 95 % du développement Ruby concerne des applications Rails. Ruby est devenu célèbre en grande partie grâce à Ruby on Rails, et si RoR décline, Ruby suivra probablement la même trajectoire que Perl, jusqu’à se réduire à une petite communauté passionnée.
      Si l’on regarde seulement le langage, je ne vois pas de raison de choisir Ruby plutôt que Python ou TypeScript. Ni côté langage ni côté plateforme, Ruby ne semble mieux faire quoi que ce soit que ses concurrents déjà mieux établis.
  • Prism est intéressant. Je me demande s’il existe des outils d’analyse de code Ruby qui l’utilisent. Je cherchais une méthode pour analyser le code de mon entreprise.

  • La variable d’environnement RUBY_MAX_CPU=n définit un maximum de N, c’est-à-dire le nombre maximal de threads natifs, avec une valeur par défaut de 8.
    Je me demande si la valeur par défaut ne devrait pas être le nombre de cœurs logiques, comme dans Rust Tokio ou de nombreux runtimes M:N.

    • C’est une optimisation qui pourra être ajoutée plus tard, avec quelques subtilités. De mémoire, Go a fonctionné de façon similaire pendant quelques années, et je me souviens qu’on définissait GO_MAX_PROCS dans init() ou main().
    • Mettre un plafond dur sur le nombre maximal de CPU ne me paraît pas correct. Il suffirait peut-être de dépendre du nombre de cœurs disponibles.
  • Dans Ruby 4.0, j’aimerais qu’on puisse utiliser des imports explicites, plutôt que la façon actuelle, implicite, d’amener les gems dans l’espace de noms global.

    • Im de Chris Salzberg pourrait vous intéresser. Il est déjà utilisable avec Ruby 3.2 : https://github.com/shioyama/im
      Il y a aussi une discussion sur la fonctionnalité encore hypothétique de « namespace on read » : https://bugs.ruby-lang.org/issues/19744
    • Qu’il soit implicite ou explicite, je trouve que l’espace de noms global convient. En théorie, c’est maladroit, mais en pratique, les conventions et les normes sociales font que cela pose rarement problème.
      Le fait que l’espace de noms global ne prenne en charge qu’exactement une version de chaque gem encourage aussi une culture saine, attachée à une ABI stable et à des périodes de dépréciation. Comparé à certains écosystèmes de langages, c’est un environnement de rêve.
    • Il me semble que c’est plutôt du côté de Rails que de Ruby, non ? Je sais que, dans la plupart des projets, la différence est pratiquement inexistante, mais c’est peut-être une décision de l’équipe Rails et sans rapport avec ce que fait l’équipe Ruby.
      Ou alors je dis peut-être complètement n’importe quoi.
    • Ruby 4.0 sera difficile à voir avant 2030.
      https://youtu.be/4MM5b2F9zrM?si=UT3aUbD6p_uBZehS&t=2347