Kaigi on Rails new LT 発表資料
https://kaigionrails.doorkeeper.jp/events/109773
#kaigionrails GraphQL Ruby をちょっとだけ速くしたGraphQL Ruby をちょっとだけ速くした@mtsmfmFumiaki MatsushimaKaigi on Rails new #kaigionrails
View Slide
#kaigionrails GraphQL Ruby をちょっとだけ速くした➔ Web Dev at Quipper➔ Dead by Daylight 仲間募集➔ 西日暮里.rb 主催➔ GraphQL Tokyo 主催@mtsmfm.inspect
#kaigionrails GraphQL Ruby をちょっとだけ速くしたhttps://nishinipporirb.doorkeeper.jp/events/108780
#kaigionrails GraphQL Ruby をちょっとだけ速くしたhttps://www.meetup.com/ja-JP/GraphQL-Tokyo/
#kaigionrails GraphQL Ruby をちょっとだけ速くした 5GraphQL とは- POST /graphql {“query”: “{ articles { title }”}したら{“data”: {“articles”: [{“title”: “Hi”}]}}を返すやつ
#kaigionrails GraphQL Ruby をちょっとだけ速くした 6社内でいくつか GraphQL を導入- あれ- これ- それ
#kaigionrails GraphQL Ruby をちょっとだけ速くした 7ある日鳴る SLO アラート- そのサービスは 90 % 300 ms- 社内サービスなので顧客に約束しているわけではないが放置は NG- 遅い GraphQL クエリがあった
#kaigionrails GraphQL Ruby をちょっとだけ速くした- これでも 200ms 弱くらい遅いクエリ8※リソース名などは実際と異なります
#kaigionrails GraphQL Ruby をちょっとだけ速くした- これすら 70ms 弱遅いクエリ9
#kaigionrails GraphQL Ruby をちょっとだけ速くした10遅いクエリ- DB?
#kaigionrails GraphQL Ruby をちょっとだけ速くした- DB? ❌- -> 起動時に YAML を読んで、そこから返している11遅いクエリ
#kaigionrails GraphQL Ruby をちょっとだけ速くした12遅いクエリ- 件数?
#kaigionrails GraphQL Ruby をちょっとだけ速くした- 件数? - -> articles が 20、relatedArticles が 50 ずつくらい- 20 * 50 = 1000- 多いしクエリの改善の余地がありそう- 実際はクエリをなんとかした- 好奇心: 多くはあるが数百ms もいくか?13遅いクエリ
#kaigionrails GraphQL Ruby をちょっとだけ速くしたプロファイリング14- GraphQL Ruby が怪しい気がする- とりあえず ruby-prof
#kaigionrails GraphQL Ruby をちょっとだけ速くした15https://ruby-prof.github.io/
#kaigionrails GraphQL Ruby をちょっとだけ速くした16ようするにこう
#kaigionrails GraphQL Ruby をちょっとだけ速くした17CallStackPrinter
#kaigionrails GraphQL Ruby をちょっとだけ速くした18%self total self wait child calls name location5.96 0.659 0.044 0.000 0.615 19241 *#resolve_value/usr/local/bundle/gems/graphql-1.11.1/lib/graphql/execution/execute.rb:2205.46 0.156 0.041 0.000 0.115 44528 Concurrent::Collection::MriMapBackend#compute_if_absent bench.rb:144.97 0.252 0.037 0.000 0.215 24284 *GraphQL::Schema::LazyHandlingMethods#after_lazy/usr/local/bundle/gems/graphql-1.11.1/lib/graphql/schema.rb:1043.96 0.079 0.029 0.000 0.049 44532 Thread::Mutex#synchronize3.95 0.036 0.029 0.000 0.007 44528 Concurrent::Collection::NonConcurrentMapBackend#_get/usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb:193.61 0.727 0.027 0.000 0.700 6456 *Hash#eachFlatPrinter
#kaigionrails GraphQL Ruby をちょっとだけ速くした19%self total self wait child calls name location5.96 0.659 0.044 0.000 0.615 19241 *#resolve_value/usr/local/bundle/gems/graphql-1.11.1/lib/graphql/execution/execute.rb:2205.46 0.156 0.041 0.000 0.115 44528 Concurrent::Collection::MriMapBackend#compute_if_absent bench.rb:144.97 0.252 0.037 0.000 0.215 24284 *GraphQL::Schema::LazyHandlingMethods#after_lazy/usr/local/bundle/gems/graphql-1.11.1/lib/graphql/schema.rb:1043.96 0.079 0.029 0.000 0.049 44532 Thread::Mutex#synchronize3.95 0.036 0.029 0.000 0.007 44528 Concurrent::Collection::NonConcurrentMapBackend#_get/usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb:193.61 0.727 0.027 0.000 0.700 6456 *Hash#eachFlatPrinter
#kaigionrails GraphQL Ruby をちょっとだけ速くした20Concurrent::Collection::MriMapBackend#compute_if_absent- map.compute_if_absent(key) { calc(key) }- ようは hash[:a] ||= ‘a’ みたいな
#kaigionrails GraphQL Ruby をちょっとだけ速くした21Concurrent::Collection::MriMapBackend#compute_if_absent- GraphQL Ruby 内では遅延評価するべきかどうかの判定に使っている (?)- graphql-batch など resolver が Promise なとき用?- 毎度 nil 返ってる
#kaigionrails GraphQL Ruby をちょっとだけ速くした22Concurrent::Collection::MriMapBackend#compute_if_absenthttps://github.com/ruby-concurrency/concurrent-ruby/blob/f749b81cb6c6291640c0004b57e60dbc2b59a72b/lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb#L21-L27
#kaigionrails GraphQL Ruby をちょっとだけ速くしたKey があっても格納された値がFalsy なときに毎回 lock とってた23https://github.com/ruby-concurrency/concurrent-ruby/blob/f749b81cb6c6291640c0004b57e60dbc2b59a72b/lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb#L22
#kaigionrails GraphQL Ruby をちょっとだけ速くしたなおした24https://github.com/ruby-concurrency/concurrent-ruby/pull/879
#kaigionrails GraphQL Ruby をちょっとだけ速くしたGraphQL Ruby Concurrent Ruby をちょっとだけ速くした@mtsmfmFumiaki MatsushimaKaigi on Rails new #kaigionrails
#kaigionrails GraphQL Ruby をちょっとだけ速くした26Warming up --------------------------------------without patch 1.000 i/100mswith patch 1.000 i/100msCalculating -------------------------------------without patch 6.782 (± 0.0%) i/s - 34.000 in 5.030646swith patch 8.633 (±11.6%) i/s - 44.000 in 5.140707sComparison:with patch: 8.6 i/swithout patch: 6.8 i/s - 1.27x (± 0.00) slower例のクエリが 1.27 倍速くなった
#kaigionrails GraphQL Ruby をちょっとだけ速くした27ご清聴ありがとうございました- 配列を返す API で、子要素も配列になっていると要素数は M* N になる (自明)- GraphQL Ruby は 20 * 50 要素 4 フィールドでも 66 ms くらい処理にかかる- Concurrent Ruby の master を使うと 54 ms くらいになる- Concurrent::Map#compute_if_absent で nil 返すのを3倍弱速くしたため- 他にも改善の余地はありそう- 簡易ベンチマークスクリプトを書いた- https://github.com/mtsmfm/graphql-ruby-benchmark-example