実際には代替は不要
ruby/json は oj よりわずかに遅いものの、その差は大きくない。
oj は性能の高さで人気があるが、さまざまな問題を引き起こす可能性がある。
oj の問題点の1つは、Oj.mimic_JSON によるモンキーパッチが原因で発生するセキュリティ上の問題である。
モンキーパッチの責任
Oj.mimic_JSON と Oj.optimize_rails は、より非効率な JSON 実装を置き換えるが、問題が発生する可能性がある。
- たとえば、
script_safe オプションを無視してしまい、XSS 攻撃に脆弱になる可能性がある。
- モンキーパッチは慎重に行うべきであり、API の進化に応じて安全に対処しなければならない。
不安定性
oj は大規模運用において、Ruby クラッシュの主要因の1つだった。
oj は非常に活発に開発されているため、新たなクラッシュが頻繁に発生する。
oj のコードベースには、信頼しにくい危ういハックが存在していた。
基礎作業
ruby/json を oj に近い性能まで改善し、モンキーパッチの必要性を減らすことを目指す。
- ベンチマークを設定し、C プロファイラを使って性能を分析した。
重複チェックを避ける
JSON.dump ベンチマークでは、重複した UTF-8 チェックを避けることで性能を改善した。
rb_enc_str_asciionly_p と isLegalUTF8 の重複処理を取り除き、3% の性能向上を達成した。
より低コストで可能性の高い条件を先に確認する
fbuffer_inc_capa 関数で、バッファがすでに割り当て済みかどうかを確認する条件を最適化し、15% の性能向上を達成した。
設定コストを減らす
ruby/json の設定コストを削減し、マイクロベンチマークで性能を大きく改善した。
ポインタ追跡を避ける
rb_enc_get 呼び出しを削除し、性能を 8% 改善した。
ルックアップテーブル
- ルックアップテーブルを使って、JSON 文字列ダンプの性能を 30% 改善した。
続き
- さらに多くの最適化があるが、それは次の記事で扱う予定である。
1件のコメント
Hacker Newsの意見
Railsでデフォルトのjbuilderを使うことは、JSONレンダリングを遅くする要因の一つである
新しいバージョンについて、TwitterのJSONダンプをパース/エンコードするのにかかる時間に関する情報があるのか気になる
このテーマに関する記事はとても理解しやすく、Rubyコードをベンチマークして最適化したくなる
素晴らしい記事と仕事である
とても面白い記事である
byrootの仕事が大好きである
Cプロファイラの助言が素晴らしかった
MameのPRで使われた"lookup table"という性能トリックが印象的だった
String#each_charの代わりにString#each_codepointを使うと、GCの負荷を減らせる自分のコードベースでさらに性能を向上させた例を共有している
Array#packを使ってコードポイントを集め、Stringに変換する現代のCPUでは分岐予測ヒントは役に立たない
Ruby JSONがintrinsicを使っているのか気になる