用 bootsnap 加速你的 Rails 啟動時間

Gary Chu
財報狗技術部落格
3 min readNov 7, 2017

寫過中大型專案的 Rails developer 都有一個共同經歷過的痛苦,就是 Rails 的 boot time 實在是太久了!

當安裝了新 gem 或修改 config 的時候,重新啟動 Rails 實在是件會讓開發效率大減的殺手(為了等 Rails 重新啟動,螢幕畫面很容易不小心就變成了 Facebook 或者 PTT,等回神時已經過了不只 10 分鐘…)

一直以來,除了換比較強的硬體以外,唯一能做的事情就是用 spring/zeus 這類 preloader 預先載入 Rails 來加速。但是以我公司的 project,即使是用了 spring,在我的 2013 MacBook Pro 跑 rails server 還是要花超過 15 秒。

不過在有了 bootsnap 後,加速 Rails boot time 這件事情又獲得了很大程度的改善。根據 Shopify(原作者在 Shopify 工作)的 benchmark,他們的 core platform 原先要花 25 秒啟動,用了 bootsnap 後只需要 6.5 秒!雖然這個是比較誇張的例子,但多數使用者回報的數據,幾乎都能減少 50% 的時間。以我們公司的 project 來說,剛好也是能減少了 50% 的時間。

註:bootsnap 和 spring / zeus 是可以共存的,兩者是透過不同的機制去加速

用起來很簡單,在 Gemfile 加上 bootsnap:

gem 'bootsnap', require: false

然後在 config/boot.rb 加上下面第二行的內容:

require 'bundler/setup'  # 原本你的 config/boot.rb 有這行
require 'bootsnap/setup' # 現在多加上這行,這兩行順序不能對調

基本上這樣就好了,不限定 development,production 原則上也可用。(另外還可以做更細微的調整,bootsnap 的 github 頁面都有說明。)

設定好後第一次執行你的 Rails 會花比較多時間(因為要產生 cache),第二次以後就可以很明顯感受到加速了。

至於為什麼可以加速?

Rails 啟動很慢一個原因是因為 Ruby 的 require 機制不太有效率,需要花很多時間去找出 require 的 class 定義在哪個檔案中。當你的 project $LOAD_PATH 數量很多時,這件事情需要花的總時間就特別久。

這個 gem 透過預先掃描好 project 中需要 require 的檔案位置後,產生一份 cache,這樣之後就不需要每次都用很沒效率的機制去掃描要載入的檔案位置。

另一個啟動很慢的原因是 Ruby VM 在每次執行 code 之前,會先把 code compile 為 bytecode 後再執行,這個動作需要花一些時間。這個 gem 預先把 code compile 出來的 bytecode cache 起來,日後直接讀取這些 cache 就好,少掉了重新 compile 的時間。

在用了這個 gem 以後,在你的 project 資料夾應該可以發現 tmp/cache 資料夾多出了 bootsnap-compile-cache 以及 bootsnap-load-path-cache,這就是這個 gem 產生出來的 cache

詳細的解釋 bootsnap 的 github 有說明,有興趣的話可以自行參考 https://github.com/shopify/bootsnap

喜歡這篇文章的話可以拍拍手讓我知道哦~
按著不放可以快速多拍幾下 :)

--

--