1 points par GN⁺ 2024-12-19 | 1 commentaires | Partager sur WhatsApp

En réalité, aucune alternative n’est nécessaire

  • ruby/json est légèrement plus lent que oj, mais l’écart n’est pas important.
  • oj est populaire pour ses performances, mais peut provoquer divers problèmes.
  • L’un des problèmes de oj est un risque de sécurité causé par le monkey patch via Oj.mimic_JSON.

La responsabilité du monkey patch

  • Oj.mimic_JSON et Oj.optimize_rails remplacent une implémentation moins efficace de JSON, mais cela peut entraîner des problèmes.
  • Par exemple, ils peuvent ignorer l’option script_safe, ce qui peut les rendre vulnérables aux attaques XSS.
  • Un monkey patch doit être appliqué avec prudence et évoluer en toute sécurité au rythme de l’évolution de l’API.

Instabilité

  • oj a été l’une des principales causes de crashs Ruby en production à grande échelle.
  • oj est développé de manière très active, si bien que de nouveaux crashs apparaissent fréquemment.
  • Le code de oj contenait des hacks douteux auxquels il était difficile de faire confiance.

Travail de fond

  • L’objectif est d’améliorer ruby/json pour atteindre des performances comparables à oj et ainsi réduire le besoin de monkey patches.
  • Des benchmarks ont été mis en place et un profileur C a été utilisé pour analyser les performances.

Éviter les vérifications en double

  • Les performances ont été améliorées dans le benchmark JSON.dump en évitant des vérifications UTF-8 redondantes.
  • La suppression du travail en double entre rb_enc_str_asciionly_p et isLegalUTF8 a permis un gain de performances de 3 %.

Vérifier d’abord les conditions les moins coûteuses et les plus probables

  • Dans la fonction fbuffer_inc_capa, l’optimisation de la condition qui vérifie si le buffer est déjà alloué a permis un gain de performances de 15 %.

Réduire le coût de configuration

  • La réduction du coût de configuration de ruby/json a fortement amélioré les performances dans les microbenchmarks.

Éviter le suivi de pointeurs

  • La suppression de l’appel à rb_enc_get a amélioré les performances de 8 %.

Table de consultation

  • L’utilisation d’une table de consultation a amélioré de 30 % les performances du dump de chaînes JSON.

À suivre

  • D’autres optimisations existent, mais elles seront abordées dans le prochain article.

1 commentaires

 
GN⁺ 2024-12-19
Avis Hacker News
  • L’utilisation par défaut de jbuilder dans Rails est l’un des facteurs qui ralentissent le rendu JSON

    • Rendre une grande partie avec jbuilder le rend lent
  • Je me demande s’il existe des informations sur le temps nécessaire à la nouvelle version pour parser/encoder le dump JSON de Twitter

  • L’article sur ce sujet est très facile à comprendre et donne envie de benchmarker et d’optimiser du code Ruby

    • Merci à l’auteur
  • Excellent article et excellent travail

    • Je me demande s’il y a encore une raison d’utiliser Oj à l’avenir
  • Article très intéressant

    • Je me demande pourquoi, pour des optimisations qui ne sont pas propres à Ruby, par exemple l’usage d’une table de correspondance pour les caractères d’échappement, on n’exploite pas des bibliothèques déjà existantes comme simdjson
  • J’adore le travail de byroot

    • Je suis toujours impressionné par ses contributions et sa productivité
    • J’aimerais participer au travail de Ruby-core, mais je perds en motivation faute de trouver quelque chose qui corresponde à mes compétences
    • Si les personnes qui travaillent sur le C de Ruby écrivaient plus souvent, il y aurait davantage de gens ayant les compétences pour faire encore progresser Ruby
  • Les conseils sur les profileurs C étaient excellents

    • Cela me donne envie de réessayer l’optimisation en ajoutant du code C à une gem Ruby
  • L’astuce de performance dite de la "lookup table" utilisée dans la PR de Mame était impressionnante

    • Utiliser String#each_codepoint au lieu de String#each_char peut réduire la charge du GC
  • Quelqu’un a partagé un exemple d’amélioration supplémentaire des performances dans sa propre base de code

    • Utiliser Array#pack pour collecter les codepoints puis les convertir en String
  • Sur les CPU modernes, les indications de prédiction de branchement sont inutiles

  • Je me demande si le JSON de Ruby utilise des intrinsèques

    • Je me demande aussi quelle est sa compatibilité avec les différents JIT