Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
RuboCop Server Mode の仕組み
Search
Hayato Kawai
March 06, 2024
1
290
RuboCop Server Mode の仕組み
「Gotanda.rb#57」で発表した LT 資料です。
https://gotanda-rb.connpass.com/event/310542/
Hayato Kawai
March 06, 2024
Tweet
Share
More Decks by Hayato Kawai
See All by Hayato Kawai
巨大 tfstate に立ち向かう技術
fohte
1
380
RubyKaigi で LT 初登壇したきっかけと感想
fohte
1
960
Datadog Logs を活用して SLO 監視基盤を構築する
fohte
3
1.3k
The Journey of rubocop-daemon into RuboCop
fohte
1
1.1k
Ruby as Shell script
fohte
1
530
rubocop-daemon 裏話: OSS の苦悩
fohte
2
600
Ruby を使ったプロダクト開発を支えるオブザーバビリティ基盤
fohte
2
150
インシデントコマンダーやってみた
fohte
5
1k
Ruby でもなんとかなる - ISUCON13 公式反省会
fohte
0
160
Featured
See All Featured
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
3.6k
Producing Creativity
orderedlist
PRO
343
39k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
28
2.2k
Become a Pro
speakerdeck
PRO
26
5.1k
Speed Design
sergeychernyshev
25
740
Statistics for Hackers
jakevdp
797
220k
The Power of CSS Pseudo Elements
geoffreycrofte
74
5.4k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
132
33k
The Cost Of JavaScript in 2023
addyosmani
46
7.2k
YesSQL, Process and Tooling at Scale
rocio
170
14k
Thoughts on Productivity
jonyablonski
68
4.4k
Designing for Performance
lara
604
68k
Transcript
RuboCop Server Mode の仕組み Gotanda.rb#57 2024-03-06 - Hayato Kawai (@fohte)
あなた誰 名前: @fohte (ふぉーて) 川井 颯人 (Hayato Kawai) 所属: ウォンテッドリー株式会社
趣味: 🎮 🎹
RuboCop 使ってますか?
持ち帰ってほしいこと • Server Mode で RuboCop の起動を高速化できる ◦ プロセスを永続化することで高速化
RuboCop を爆速にしたい • RuboCop は速くない ◦ だいたい 2 秒〜 かかる
▪ 1 ファイルに対しても 1 秒前後かかる ◦ コーディング中はすぐにフィードバックしてほしい ▪ 1 秒も待ちたくない!
rubocop-daemon gem を作りました (2018 年)
RuboCop 本体に 取り込まれました 🎉 (2022 年) https://github.com/ruboco p/rubocop/pull/10706 Big Thanks
to @koic
詳しくは RubyKaigi 2022 の @koic さんの発表にて https://speakerdeck.com/koic/make-rubocop-super-fast
注意事項 • 今回は rubocop-daemon の実装を紹介します ◦ RuboCop の Server Mode
と内部実装は同じなので、読み替え可能 ◦ rubocop-daemon と Server Mode はコマンド体系が少し異なります ◦ 詳細はドキュメントを参照してください : https://docs.rubocop.org/rubocop/usage/server.html
RuboCop はコマンド実行のたびに読み込み直すから遅い • 通常の RuboCop はコマンド実行のたびに RuboCop を読み込む $ rubocop
… require 'rubocop' RuboCop::CLI.new.run ターミナル RuboCop $ rubocop … require 'rubocop' RuboCop::CLI.new.run
RuboCop はコマンド実行のたびに読み込み直すから遅い • この中でも require 'rubocop' が遅い $ rubocop …
require 'rubocop' RuboCop::CLI.new.run ターミナル RuboCop $ rubocop … require 'rubocop' RuboCop::CLI.new.run
require 'rubocop'は遅い % ruby -rbenchmark -e '$LOAD_PATH.unshift("/path/to/rubocop/lib"); Benchmark.bm { |x|
x.report { require "rubocop" }}' user system total real 0.573636 0.217166 0.790802 ( 0.815585) https://github.com/rubocop/rubocop/pull/10706#issuecomment-1152382752
require 'rubocop'は遅い • require 'rubocop' のみで約 0.8 秒かかる ◦ RuboCop
のコア機能である「lint」は処理していない ▪ lint するともう少し時間はかかるが、 1 ファイルだけであれば短い ▪ ファイル数に比例して長くなる
require 'rubocop'は遅い • 💡 つまりこれをキャッシュすればよいのでは? ◦ これが rubocop-daemon のアプローチ
rubocop-daemon の高速化アプローチは単純 • require 'rubocop' したプロセスを サーバーとして用意 (デーモン化) ◦ このサーバーにリクエストする
◦ アプリケーションサーバーを起動し続け、リクエストを待ち受けて処理するのと同じ rubocop-daemon (server) $ rubocop-daemon exec … ターミナル $ rubocop-daemon exec …
rubocop-daemon の RuboCop 実行フロー • rubocop-daemon をサーバーとして起動する rubocop-daemon (server)
rubocop-daemon の RuboCop 実行フロー • rubocop-daemon サーバーにリクエストする ◦ サーバーでは RuboCop
の内部メソッド (RuboCop::CLI#run) を 呼び出している rubocop-daemon (client) rubocop-daemon (server) 1. RuboCop 実行 リクエスト
rubocop-daemon の RuboCop 実行フロー • サーバーが lint 結果を返す rubocop-daemon (client)
rubocop-daemon (server) 1. RuboCop 実行 リクエスト 2. 実行結果返却
❯ ruby -rbenchmark -e 'Benchmark.bm { |x| x.report { `rubocop
/path/to/file 2>&1 >/dev/null` }}' user system total real 0.000099 0.000637 0.602601 ( 0.886394) ❯ ruby -rbenchmark -e 'Benchmark.bm { |x| x.report { `rubocop-daemon exec -- /path/to/file 2>&1 >/dev/null` }}' user system total real 0.000050 0.000564 0.073490 ( 0.090813) • 実行時間が 0.89 秒 -> 0.09 秒 (約 10 倍速) に短縮 🎉 rubocop-daemon で 10 倍弱高速化できる
余談: 今は LSP Mode もある • RuboCop 1.53 から LSP
Mode が追加された ◦ https://docs.rubocop.org/rubocop/usage/lsp.html • LSP = Language Server Protocol ◦ VSCode 発 ◦ エディタ上でコード補完や定義元ジャンプなど様々な機能を提供するための プロトコル ▪ LSP サーバーに対し、エディタがサーバーに問い合わせる ▪ Server Mode と同じような仕組み
LSP Mode と Server Mode はプロトコルが違うだけ • LSP Mode: LSP
を喋る ◦ JSON-RPC でフォーマットが策定されている ◦ 通信は TCP/IP が多い • Server Mode: 独自プロトコルを喋る ◦ "#{token} #{dir} #{command} #{args}\n#{body}" というフォーマット ▪ RuboCop では version 情報が追加されていたりする ◦ 通信は TCP/IP
エディタから使うなら LSP Mode がよさそう • LSP は多くのモダンなエディタで実装されている ◦ プラグインが提供されている場合も多い •
Server Mode だと、エディタが Server Mode の プロトコルを喋る必要がある ◦ それ用の実装が必要 ◦ エディタから rubocop コマンドを実行するのも手 ▪ ただしサーバーに通信するための処理もあるので若干のオーバーヘッドがある
(再掲) 持ち帰ってほしいこと • Server Mode で RuboCop の起動を高速化できる ◦ プロセスを永続化することで高速化
(宣伝) 明日裏話をします Omotesando.rb #95 にて OSS の苦悩をはなします