概要
携わっている案件で作成しているRailsアプリケーションでは、JSONシリアライザとしてRablを採用していました。しかしどうもRablが遅い。
そこで、さまざまなシリアライザを比較してみることにしました。
世間では"ActiveModel Serializerが圧倒的に早いぞ!"というのをよく見るが、だいたいの検証記事はひとつのモデルのインスタンスをそのままシリアライズするような場合。
関連するモデルの情報を含めたり、モデルの属性から算出する値を含めたりする場合の性能比較は見つかりません。
そこで、より現実に即した状況で性能を比較検討してみましたというものです。。
全選手入場!!
比較対象は次のよっつ。
- ActiveModel::Serializer
- Grape::Entity
- Jbuilder (個人的には一番書きやすくて好き)
- Rabl
バージョンはそれぞれ
- active_model_serializers: 0.10.6
- grape-entity: 0.6.1
- jbuilder: 2.7.0
- rabl: 0.13.1
また、Ruby, Railsなどは
Ruby2.4.1、Rail5.1.3、Grape1.0.0を使用。
サンプルアプリケーション
構成
User, Article, Bookmarkの3つのモデルが存在する。
API
存在するAPIはユーザー情報を取得するAPIで、次のようなJSONを返す。
Userの属性と、そのUserに紐づくArticleの属性、そして各ArticleとUserに紐づくBookmarkが存在するかどうかを "is_bookmark" で表している。
{
"user": {
"id": 1,
"name": "user0",
"articles": {
"id": 1,
"title": "title0",
"content": "content0",
"is_bookmarked": true"
}
}
}
リポジトリ
環境
実行環境は13インチのMacbook Pro。
ベンチマーク
設定
事前にUserを100、Articleを1000(User 1あたり10)、Bookmarkを30000(User1あたり300)作成してある。
User IDに含まれる数からランダムに1000個の数字列を生成し、そのIDを使ってAPIリクエストを行う。
10000リクエストをさばくのにかかった秒数を計測した。
結果
シリアライザ | 時間 |
---|---|
ActiveModel::Serializer | 121 |
Grape::Entity | 99 |
Jbuilder | 138 |
Rabl | 130 |
おおまかに Grape::Entity < ActiveModel::Serialiser < Jbuilder < Rabl (上記ではRablのほうがJbuilderより小さい数字になっているが、Jbuilderのほうが早いケースのほうが多い。外れ値を除けばよかった、、。)
という傾向が得られた。特にGrape::Entityはほかと比べて際立って早い場合が多く、Rablとの比較では20%近く早くなりそう。
早い早いと評判だったActiveModel::Serializerは言うほど早くないような。
備考
CPUを多用するベンチマークであるため、ベンチマーク実行中にCPU温度が高くなり周波数が下がるケースがみられた。その影響が出にくくなるよう、ベンチマーク実行中はPCを冷却台で冷やし、実行順を変えて平均をとった
とはいえ
パフォーマンスをそこまで気にしないのであれば、jbuilderが圧倒的に書きやすいかなぁ…と個人的に思います。あくまで個人的な感想ですが、今回のサンプルAPIを作成した際に感じたとっつきやすさは
jbuilder >> Rabl > Grape::Entity >>> ActiveModel::Serializer
という感じです。