1 Punkte von GN⁺ 2024-12-19 | 1 Kommentare | Auf WhatsApp teilen

Eigentlich ist keine Alternative nötig

  • ruby/json ist etwas langsamer als oj, aber der Unterschied ist nicht groß.
  • oj ist wegen seiner Performance sehr beliebt, kann aber verschiedene Probleme verursachen.
  • Eines der Probleme von oj sind Sicherheitsprobleme durch Monkey-Patching via Oj.mimic_JSON.

Die Verantwortung von Monkey-Patches

  • Oj.mimic_JSON und Oj.optimize_rails ersetzen weniger effiziente Implementierungen von JSON, dabei können jedoch Probleme auftreten.
  • Zum Beispiel kann die Option script_safe ignoriert werden, wodurch eine Anfälligkeit für XSS-Angriffe entstehen kann.
  • Monkey-Patches sollten mit Vorsicht vorgenommen werden und müssen sicher mit der Weiterentwicklung der API umgehen.

Instabilität

  • oj war in groß angelegten Produktivumgebungen eine der Hauptursachen für Ruby-Abstürze.
  • oj wird sehr aktiv weiterentwickelt, daher treten häufig neue Abstürze auf.
  • In der Codebasis von oj gab es schmutzige Hacks, denen man nur schwer vertrauen konnte.

Grundlagenarbeit

  • ruby/json soll auf eine mit oj vergleichbare Performance verbessert werden, um die Notwendigkeit von Monkey-Patches zu verringern.
  • Es wurden Benchmarks eingerichtet und ein C-Profiler verwendet, um die Performance zu analysieren.

Doppelte Prüfungen vermeiden

  • Im JSON.dump-Benchmark wurde die Performance verbessert, indem doppelte UTF-8-Prüfungen vermieden wurden.
  • Durch das Entfernen doppelter Arbeit in rb_enc_str_asciionly_p und isLegalUTF8 wurde eine Performance-Steigerung von 3 % erreicht.

Zuerst die billigeren und wahrscheinlich zutreffenden Bedingungen prüfen

  • In der Funktion fbuffer_inc_capa wurde die Bedingung dafür optimiert, ob der Buffer bereits zugewiesen ist, was zu einer Performance-Steigerung von 15 % führte.

Overhead der Konfiguration reduzieren

  • Durch die Reduzierung des Konfigurations-Overheads von ruby/json wurde die Performance in Mikro-Benchmarks deutlich verbessert.

Pointer-Chasing vermeiden

  • Durch das Entfernen des Aufrufs rb_enc_get wurde die Performance um 8 % verbessert.

Lookup-Tabellen

  • Durch den Einsatz von Lookup-Tabellen wurde die Performance beim Dumpen von JSON-Strings um 30 % verbessert.

Fortsetzung folgt

  • Es gibt noch weitere Optimierungen, die im nächsten Beitrag behandelt werden.

1 Kommentare

 
GN⁺ 2024-12-19
Hacker-News-Kommentare
  • Die standardmäßige Verwendung von jbuilder in Rails ist einer der Faktoren, die das JSON-Rendering verlangsamen

    • Wenn große Teile mit jbuilder gerendert werden, wird es langsam
  • Ich frage mich, ob es Informationen dazu gibt, wie lange die neue Version zum Parsen/Kodieren des Twitter-JSON-Dumps braucht

  • Der Artikel zu diesem Thema ist sehr leicht verständlich und macht Lust darauf, Ruby-Code zu benchmarken und zu optimieren

    • Danke an den Autor
  • Ein großartiger Artikel und tolle Arbeit

    • Ich frage mich, ob es künftig noch einen Grund gibt, Oj zu verwenden
  • Ein sehr interessanter Artikel

    • Ich frage mich, warum man bei Optimierungen, die nicht auf Ruby beschränkt sind, etwa bei der Verwendung einer Lookup-Tabelle für Escape-Zeichen, nicht bereits existierende Bibliotheken wie simdjson nutzt
  • Ich liebe die Arbeit von byroot

    • Ich bin immer wieder überrascht von seinen Beiträgen und seiner Produktivität
    • Ich würde mich gern an der Ruby-core-Arbeit beteiligen, aber finde nichts, das zu meinen Fähigkeiten passt, daher fehlt mir die Motivation
    • Wenn Leute, die mit Ruby-C zu tun haben, häufiger schreiben würden, gäbe es mehr Menschen mit den nötigen Fähigkeiten, um Ruby weiter voranzubringen
  • Der Rat zum C-Profiler war hervorragend

    • Ich möchte erneut versuchen, eine Optimierung umzusetzen, indem ich C-Code zu einem Ruby-Gem hinzufüge
  • Der Performance-Trick mit der "Lookup-Tabelle" aus Mames PR war beeindruckend

    • Die Verwendung von String#each_codepoint statt String#each_char kann die GC-Last verringern
  • Es wurde ein Beispiel geteilt, das die Performance in der eigenen Codebasis weiter verbessert hat

    • Mithilfe von Array#pack werden Codepoints gesammelt und in einen String umgewandelt
  • Auf modernen CPUs sind Hinweise für die Branch Prediction nutzlos

  • Ich frage mich, ob Ruby JSON Intrinsics verwendet

    • Mich interessiert auch die Kompatibilität mit verschiedenen JITs