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
Fukuoka.rb_0x100_LT.pdf
Search
Yusuke Iwaki
May 11, 2022
Technology
480
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Fukuoka.rb_0x100_LT.pdf
Yusuke Iwaki
May 11, 2022
More Decks by Yusuke Iwaki
See All by Yusuke Iwaki
Playwrightのソースコードに見る、自動テストを自動で書く技術
yusukeiwaki
15
7.2k
あなたのWebサービスはAIに自動テストしてもらえる?アクセシビリティツリーで読み解く、AIの『視点』
yusukeiwaki
1
9.1k
個人開発から公式機能へ: PlaywrightとRailsをつなげた3年の軌跡
yusukeiwaki
12
9.1k
Capybara+生成AIでどこまで本当に自然言語のテストを書けるか?
yusukeiwaki
7
5.9k
ChatGPTを個々人が使っていた組織から チームチャットにボットを棲まわせて みんなが活用する組織になるまでの変遷 ぜんぶ紹介しちゃいます
yusukeiwaki
0
3.5k
E2E testing on Rails 2023
yusukeiwaki
4
3.6k
Railsの システムテスト解剖学
yusukeiwaki
8
8.1k
RailsのSystem specから 🎭Playwrightを使う
yusukeiwaki
2
16k
puppeteer-ruby: Ruby/Railsのためのブラウザオートメーションツール
yusukeiwaki
0
1.8k
Other Decks in Technology
See All in Technology
多摩川(.dev)ランニング入門 / Tamagawa.dev#3
fujiwara3
3
320
データエンジニアリングワークショップ:Auto LoaderとSparkで学ぶデータパイプライン構築
databricksjapan
PRO
0
140
全員がプロダクトへ向き合う組織を持続成長させるために——組織づくりのフライホイールと4象限 / The Flywheel Model and Four Quadrants for Organizational Design
hiro_torii
3
740
設計の世代交代を乗り越える、14年続くAndroidアプリの開発戦略
sansantech
PRO
1
110
AI時代に、プロダクトの数だけ積み上がる所有コストをどうエンジニアリングするか / Engineering the Cost of Ownership
kzkmaeda
0
930
分割40%キーボードにスムーズに入門するには
hoto17296
1
230
少人数データチームのDevin活用実践事例
runandy16
2
430
ブラウザアプリの継続的パフォーマンスモニタリング (序) / Continuous Browser Application Performance Monitoring; Act 1
moznion
0
100
20260903 Tokyo Jazug Night #62 | Azure エンジニアよ、 その環境は本当にセキュアか?
olivia_0707
1
610
スクラムで身についていた動き方を、XPで捉え直してみた
codmoninc
1
170
AI-DLCって実際どう? 〜聞きたいこと全部聞いてみる〜
news_it_enj
0
210
PdMをやめて、 "プロダクトビルダー"という 働き方に変えました / PdM to Product Builder
shikichee
2
680
Featured
See All Featured
Testing 201, or: Great Expectations
jmmastey
46
8.3k
What does AI have to do with Human Rights?
axbom
PRO
1
2.4k
Typedesign – Prime Four
hannesfritz
42
3.2k
Facilitating Awesome Meetings
lara
57
7.1k
Become a Pro
speakerdeck
PRO
31
6.2k
Paper Plane (Part 1)
katiecoart
PRO
1
10k
How to Ace a Technical Interview
jacobian
281
24k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
35
2.8k
Highjacked: Video Game Concept Design
rkendrick25
PRO
1
450
Building the Perfect Custom Keyboard
takai
2
860
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
560
GitHub's CSS Performance
jonrohan
1033
470k
Transcript
async/await Rubyでどう書く? Fukuoka.rb 0x100 LT @YusukeIwaki
About @YusukeIwaki • 仕事:天神にある会社で、Railsアプリケーションの開発 ◦ 生まれは富山、大学は京都、1社目は札幌、2018年に福岡に移住 • puppeteer-rubyとかplaywright-ruby-clientとか作ってる人 ◦ ブラウザを自動操作するやつ
◦ Rubyでブラウザ操作するのに、Selenium以外の選択肢を作りたい。
Fukuoka.rb 0x0100回おめでとうございます • Kaigi on Rails 2021登壇のきっかけは、Fukuoka.rbの夜会 ◦ 夜の23時まで開いているRubyコミュニティは多分ここだけ? ◦
福岡にゆかりのあるひともないひともつながれるRubyコミュニティは素晴らしい ◦ 今後もゆるゆるとRubyを盛り上げていきましょう
本日の話 async / await ってRubyだとどうやって使えばいいの?
JSの有名ライブラリ Railsから使いたい! →Rubyに移植したい! async Promise then catch Promise.all Promise.race await
おそらく以下のどっちかが現実解 • 思考停止でconcurrent-rubyを使う ◦ とくにRailsアプリケーションだったら手軽 • めっちゃ考えてAsync gemを使う ◦ シングルスレッド動作で最大限のパフォーマンスが出せる
(memo) ここまで1分
おさらい: RubyのThreadとFiber • Thread→思考停止で、2つ以上の処理を同時に流せる • Fiber→ゆずりあいで、2つ以上の処理をかわりばんこに流す ◦ 合言葉は Fiber.yield
% ruby fiber.rb 0 1 2 3 4 0 1
2 3 4 % ruby thread.rb 0 0 1 1 2 2 3 3 4 4
async/await in Ruby • 思考停止でconcurrent-rubyを使う ◦ Threadベース ◦ とくにRailsアプリケーションだったら手軽 •
めっちゃ考えてAsync gemを使う ◦ Fiberベース ◦ シングルスレッド動作で最大限のパフォーマンスが出せる
(memo) ここまで2分半
concurrent-rubyでの async/await Promise Concurrent::PromisesモジュールのFutureを使う。 https://github.com/ruby-concurrency/concurrent-ruby/blob/master/docs- source/promises.in.md
concurrent-ruby: 2種類のFuture Concurrent::Promises.future { ….. ; 123 } • 裏で処理をやって、結果として123を返す
• Thread.newと同じ使い勝手で、さらに実行結果をもらえるイメージ f = Concurrent::Promises.resolvable_future, f.fulfill(123) , f.reject(err) • スレッドセーフな箱を作って、結果123を別スレッドから入れてもらう • JSのPromiseのような使い勝手
concurrent-ruby: Futureのチェーン、結果待ち受け future.then { |result| … ; next_result }.then {
|next_result| … } • JSのPromise#then, Promise#catch に限りなく近い future.value! • futureの結果をもらう。 • futureの結果がまだ出ていない場合には、結果が出るまでブロッキング。 Concurrent::Promises.zip(future1, future2, …) • 全部の結果が出揃うのを待つ。JSのPromise.allと同じ。
async click(x, y) { const point = await clickablePoint(x, y)
await scrollToPosition(x, y) await Promise.all([ mouse.down(x, y), mouse.up(x, y), ]) } def click(x, y) Concurrent::Promises.future do point = clickable_point(x, y).value! scroll_to_position(x, y).value! Concurrent::Promises.zip( mouse.down(x, y), mouse.up(x, y), ).value! end end concurrent-rubyを使ったasync/awaitっぽい実装 ※ 擬似コードです
でも気をつけろ!concurrent-rubyはThreadベースだ!
None
None
Async gem https://rubykaigi.org/2019/presentations/ioquatix.html
ノンブロッキングI/Oを活用し、IO待ちの間に別の処理を行う • シングルスレッドのFiberベースなので、オーバーヘッドが非常に少ない Ruby 2.xで利用するときには ノンブロッキングI/Oベースの各種ライブラリを併用する必要がある Async gem
Async { … } / Async::Reactor.run { … } •
処理のかたまり(task)を定義する ◦ JSの async () => { … } と似ている • トップレベルで利用するときと、ネストで利用するときとで挙動が違う ◦ トップレベルで利用時・・・サブタスクが全部終わるまで待つ ◦ ネストで利用時・・・サブタスクを作成し、スケジュール ◦ これも JSの async function呼び出しの挙動と似ている Async gemの基本
q = Async::Queue.new, q.dequeue, q.enqueue(hoge) • q.dequeueを呼ぶと、誰かがq.enqueueするまで待つ • q.dequeueよりも先に誰かがenqueue(hoge)していたら、即座にhogeが返る •
ほぼPromise cond = Async::Condition.new, cond.wait, cond.signal(hoge) • cond.waitを呼ぶと、誰かがcond.signalするまで待つ • cond.waitよりも先に誰かがcond.signal(hoge)しても、signalは捨てられる • 自前でPromiseっぽい何かを作る材料になる Async::Barrier, Async::Semaphore • サブタスク全部が終わるまで待つ、サブタスクの同時実行数を制限する • Promise.all 的なものを作る材料になる Async gemを使って async/await Promise
async click(x, y) { const point = await clickablePoint(x, y)
await scrollToPosition(x, y) await Promise.all([ mouse.down(x, y), mouse.up(x, y), ]) } def click(x, y) Async do point = clickable_point(x, y).wait scroll_to_position(x, y).wait barrier = Async::Barrier.new barrier.async { mouse.down(x, y).wait } barrier.async { mouse.up(x, y).wait } barrier.wait end end Async gemを使ったasync/awaitっぽい実装 ※ 擬似コードです
でも気をつけろ!Async gemはFiberベースだ! • 思考停止で使うと、並列処理されない(当然) • 不用意にwaitすると、メインスレッドがブロックされ全部が動かなくなる • Ruby 2.7で使いたいならノンブロッキングI/Oベースのライブラリ導入に そこそこ対応工数がかかる
ただ、用途があえば • すんごい速い • すんごい安定 ◦ 「ときどき処理順序がひっくり返ってしまって困る・・・」のような Threadベースだと起きる問題がFiberベースでは起きない
(memo) ここまで4分
まとめ:async/await in Rubyの現実解 • 思考停止でconcurrent-rubyを使う ◦ とくにRailsアプリケーションだったらもともと入ってるので手軽 ◦ Threadベースなので、処理順序性の保証とかほぼない •
めっちゃ考えてAsync gemを使う ◦ Fiberベースのシングルスレッド動作で最大限のパフォーマンスが出せる ◦ JSのasync functionに近い動作 ◦ Ruby 2.7環境で既存のアプリケーションに導入するのは結構たいへん
DEMO