Rails:「Pagy」gemでRailsアプリを高速ページネーション(翻訳)|TechRacho(テックラッチョ)〜エンジニアの「?」を「!」に〜|BPS株式会社エンジニアの「?」を「!」に。原著者の許諾を得て翻訳・公開いたします。Railsがバージョン0.8の頃から開発者として使っていることもあり、その間に誇大広告気味のRubyGemを星の数ほど目にしてきました。成熟したソフトウェア開発コミュニティと同様、特定の用途では事実標準のgemとして永らえているライブラリもありますが、他の多くのライブラリは誰もサポートしてくれないまま、採用に値しない瓦礫の山を築いています。用途によっては1つや2つgemをあえて追加することもありますが、ほとんどどの機能にもそれぞれに相応しいチャンピオンが君臨しているものです。以下の図は、ここ10年の間に新しいライブラリやアイデアにコミュニティが貢献した様子を示しています。当初のgem数は増加していますが、2015年をピークに以後は減少しています(成熟したとも言えるでしょうか)。私は、2018年のgem数は2009年とほぼ同レベルであろうと睨んでおり、この傾向が続くならば新しいgemの数は今後も減少し続け、安定期に入るでしょう。ここからさまざまな疑問が湧き起こります。私としては、このデータだけでは何とも言えません。した視点とは違うアプローチによって、今日の私たちの仕事に大きなインパクトをもたらす部分に着目してみたいと思います。新しいgemの数が減少するに連れて、今の私たちの仕事に大きく影響するような画期的なものはなかなか出現しなくなるだろうと考えられます。そんなことはありません。それを今から証明いたします。Railsで開発したことがある方なら、アプリのindexページをwill_paginateやKaminariでページネーションしたことがおそらくあるでしょう。Rails経験の浅い方なら、今後そうしたページネーションgemを探すことになるでしょう。PagyはRails向けの新しいページネーションライブラリです。パフォーマンスを念頭に置いて開発されており、かつ新規または既存のRailsアプリの使いやすさを損ないません。はい、今皆さんが思っていることを当ててみせましょう。「お、今度のページネーションgemこそ俺たちが求めていたもの...なわけないだろ!」そこについては私も同感です。オープンソースでソリューションが分散してしまうのはよくないと思います。gemによってもたらされる改良点のいくつかは、既にKaminariでも実装が提案されたのですが、リジェクトされました。改善にはKaminariのコア部分で大規模な変更が避けられなかったからでしょう。何かが華々しく登場したら、ときにはそれが本当にベストなのかどうか一歩身を引いて考える必要があると、私は固く信じています。ページネーションについて言うなら、このgemには疑いの余地はありません。理由を説明しましょう。この図がすべてを物語っていると私は信じています。アプリが数百〜数千ものユーザーを同時にさばいている状態では、ちっぽけな機能を1つ足すだけでもリソースに大きな影響を及ぼすことは容易に想像が付きます。20ページに対して実施した1つのテストの結果を見ると、will_paginateはうまくやっている一方、Kaminariのメモリ容量は著しく増大しています。Pagyはwill_paginateよりさらに優秀です。数千人ものユーザーをさばこうとするとき、この違いがもたらすインパクトを今一度考えてみてください。詳しく見てみましょう。今度はそれぞれのgemのメモリフットプリントを比較します。Kaminariと同じジョブを、Pagyは遥かに少ないメモリで実行できます。will_paginateもKaminariより省メモリではあるものの、Pagyと比べると7倍にものぼります。皆さまに考慮いただきたいのは、will_paginateが最後にリリースされたのは1年も前のことで、リポジトリにはプルリクが何十個もたまったまま、最終コミットの日付は2017年7月のままになっている点です。今仮に新規プロジェクトがスタートすることがあったとしても、will_paginateは選択肢には含めないでしょう。はい、皆さんはここできっとこう思うでしょう。「よっしゃ気に入った。ところでPagyが他のgemと比べてメモリフットプリントがここまで少ない理由が謎なんだけど、どうやってんの?」よくぞ聞いてくださいました。ご説明いたしましょう。実は私も、当初同じ疑問を抱いたのでした。「Kaminariが生成するオブジェクト数が6,000個超えってどういうこと?」もちろんwill_paginateの方が省メモリではあるものの、それでも20ページのページネーションでオブジェクト数が3,000個超えというのはあんまりです。Pagyのオブジェクト数は400個を下回っています。Pagyの方が優秀な理由pagyのどこがそんなに違うのでしょうか?ご説明いたします。PagyはRubyオブジェクトではなくintegerで計算しているPagyのコアコードは60行にも満たないPagyはアプリのモデルに癒着しておらず、HTMLやURLや複数形化(pluralization)や式展開を独自に生成する。Pagyは、一般的なヘルパーではなく完全に特殊化したコードを用いている。コードが専門化していることで、作者が1行ずつ丁寧にベンチマークを取っている(コードが100行もなければ十分可能です)。gemのコードはきわめて理解しやすいという実にうれしいおまけまでついています。拡張で機能を追加することも可能で、いくつかの拡張は組み込み済みなのですぐにでも使えます。私がRailsアプリを開発した当初はwill_paginateを使っていましたが、その理由は当時はその業務にベストだったからです。数か月後にKaminariがリリースされると、そちらに乗り移りました(なにぶんあまりにも昔のことなので、乗り換えた理由はよく思い出せません)。数週間前にPagyがリリースされるまで、Kaminariを使い続けていました。私が初めてPagyを知ったときに心底愕然としたのは、私がwill_paginateからKaminariに移行したときにパフォーマンスのことをまったく考慮していなかったことでした。後者は前者よりずっと遅かったにもかかわらず、です。今の私はパフォーマンスを考慮することを覚えました。これまで私たちが設計・リリースしたアプリで、いったいいくつのgemを取り入れてはパフォーマンスを下げまくっていたことでしょう。will_paginateやKaminariからPagyへの移行は実に簡単で、必要なコードはわずか数行で済みます。次回の私の記事では皆さまに関心を持っていただけるよう、具体的な移行方法を解説することをお約束いたします。本記事の画像およびパフォーマンスはPagyの作者が行ったベンチマークテストを用いています。ベンチマークのソースコードはddnexus/pagination-comparisonでご覧いただけます。RubyGem採用の推移チャートには、こちらでご覧いただけるRubyGems.orgのデータを用いております。コボラー、ITコンサル、ローカライズ業界、Rails開発を経てTechRachoの編集・記事作成を担当。チュートリアル第2版の監修および半分程度を翻訳、Railsガイドの初期翻訳ではほぼすべてを翻訳。その後も折に触れて更新翻訳中。enno.jpを運営。実は最近Go言語が好きで、Goで書かれたRubyライクなGoby言語のメンテナーでもある。仕事に関係ないすっとこブログ「あけてくれ」は2000年頃から多少の中断をはさんで継続、現在はnote.muに移転。Storageを使ってはいけない(翻訳)#Tags#会社紹介#自社サービス#勉強会#Rails#PHP#デザイン#実績#週刊RailsウオッチCONTACTお気軽にご相談ください。(翻訳)CONTACTTechRachoでは、パートナーシップをご検討いただける方からのご連絡をお待ちしております。お気軽にご意見・ご相談ください。