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
950
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
Git: the NoSQL Database
bkeepers
PRO
427
64k
Raft: Consensus for Rubyists
vanstee
137
6.7k
Building Adaptive Systems
keathley
38
2.4k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
192
16k
A designer walks into a library…
pauljervisheath
205
24k
Learning to Love Humans: Emotional Interface Design
aarron
274
40k
Facilitating Awesome Meetings
lara
51
6.2k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
26
1.9k
Bootstrapping a Software Product
garrettdimon
PRO
305
110k
jQuery: Nuts, Bolts and Bling
dougneiner
62
7.6k
A better future with KSS
kneath
238
17k
RailsConf 2023
tenderlove
29
970
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 の苦悩をはなします