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
390
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
Datadog が支える Wantedly のシステム運用
fohte
0
40
Devin や Cursor などの生成 AI ツール導入に向けて何を取り組んだのか
fohte
2
250
Datadog Network Monitoring を活用して NAT Gateway 課金を 80 % 削減した話
fohte
2
670
Trace Metrics と Istio Metrics でサービス健全性を監視する
fohte
0
470
段階的リリースを実現する kube canary
fohte
1
200
巨大 tfstate に立ち向かう技術
fohte
1
930
RubyKaigi で LT 初登壇したきっかけと感想
fohte
1
1.3k
Datadog Logs を活用して SLO 監視基盤を構築する
fohte
3
2.6k
The Journey of rubocop-daemon into RuboCop
fohte
1
1.4k
Featured
See All Featured
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
140
34k
Large-scale JavaScript Application Architecture
addyosmani
514
110k
Rails Girls Zürich Keynote
gr2m
95
14k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.5k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
252
21k
Optimizing for Happiness
mojombo
379
70k
Designing for Performance
lara
610
69k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
19
1.2k
Intergalactic Javascript Robots from Outer Space
tanoku
273
27k
Become a Pro
speakerdeck
PRO
29
5.5k
Embracing the Ebb and Flow
colly
88
4.8k
Learning to Love Humans: Emotional Interface Design
aarron
274
41k
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 の苦悩をはなします