Railsで11sかかるリクエストを0.5sにした話

Railsで11sかかるリクエストを0.5sにした話

 

qiita.com


m

# 高速化の手筈を整える
リクエストを高速化するためには、まず遅い原因を見つけることが大事!

# rack-mini-profilerの導入
コードの実行からレンダーまでの内訳を分析できるので、Rails高速化の分析には必須

# rack-mini-profilerの恩恵
- N + 1問題
- 実際のSQL
- slow query
Railsで実装するとActiveRecordSQLをよしなに組み立ててくれるため、ちょっと違和感のあるSQLが多々ある。

# 具体的に何が確認できるの
ここで確認できることは
- SQL の中身と時間
- レンダーにかかる時間


```
$ vi Gemfile


gem 'rack-mini-profiler', require: false

```

# rack-mini-profilerの開発環境での準備

```
$ bundle exec rails g rack_profiler:install
```

# rack-mini-profilerの設定ファイル

```
$ vi config/initializers/rack_profiler.rb

if Rails.env == 'development'
require 'rack-mini-profiler'

# initialization is skipped so trigger it
Rack::MiniProfilerRails.initialize!(Rails.application)
end

```

# 準備は整ったので分析開始
Rails serverを再起動すると画面左上にページのロードにかかった時間が表示されるようになる。


# あれ、画面左上にないよ!
僕の環境の場合、htmlファイルじゃないと表示されなかったので、
実際の該当ページをリロードして、そのあと別タブで自分のサイトの404のURLを叩いて確認しました!


# あれQueryが以上に多い
そ、それは、N+1 問題の可能性が大きい。
具体的に話すとeach分の中でexists?などオブジェクトの検索がかかると再度Queryが走るため要注意。

サンプルコード

```
articles.each do |article|
if article.comments.exists? # ここでN+1です
puts article.comments.author
end
end
```

 

# あとは遅いクエリーを徹底的に速くする
雑に書くと

```
class ArticleService
def recommend_article_first
article = Article.recommend_article.first
#ここでarticleがN回呼び出される
{
id: article.id,
url: article.url,
title: article.title,
category_id: article.category_id,
}
end
end
```

#なんでこれがだめか

文法的におかしいだろは置いといてObjectを生成してみると分かる通り、毎回違うObjectが生成されていることがわかります。


# だめな例
```

class Onigiri
def hello
puts "Hello"
end
end

puts Onigiri.new.object_id
70283626235260
=> nil
puts Onigiri.new.object_id
70283622696580
=> nil
puts Onigiri.new.object_id
70283626251680
=> nil

```

オブジェクトが再生成されないことがわかる

# 良い例
```

class Onigiri
def hello
puts "Hello"
end
end

@onigiri = Onigiri.new
=> #<Onigiri:0x007fd85d264110>
puts @onigiri.object_id
70283626225800
=> nil
puts @onigiri.object_id
70283626225800
=> nil
puts @onigiri.object_id
70283626225800
=> nil

```
毎回同じObjectが使われていることがわかります。

#実際の使い方
```
class Onigiri
# 例1
def hello
@hello ||= puts "Hello"
end

# 例2
def world
@world ||= Begin
world= puts "World!"
end
end
end
```

# 最後に言いたいこと

高速化には、実際の遅い要因を把握することが大事で、それに対して必ず適切な方法があるので、頑張って見つけることが重要!
Rubyは幸いにもドキュメントが充実してるので比較的高速化しやすい言語かと!