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
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Yusuke Iwaki
May 11, 2022
Technology
470
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.1k
あなたのWebサービスはAIに自動テストしてもらえる?アクセシビリティツリーで読み解く、AIの『視点』
yusukeiwaki
1
8.9k
個人開発から公式機能へ: PlaywrightとRailsをつなげた3年の軌跡
yusukeiwaki
12
8.9k
Capybara+生成AIでどこまで本当に自然言語のテストを書けるか?
yusukeiwaki
7
5.8k
ChatGPTを個々人が使っていた組織から チームチャットにボットを棲まわせて みんなが活用する組織になるまでの変遷 ぜんぶ紹介しちゃいます
yusukeiwaki
0
3.4k
E2E testing on Rails 2023
yusukeiwaki
4
3.5k
Railsの システムテスト解剖学
yusukeiwaki
8
8k
RailsのSystem specから 🎭Playwrightを使う
yusukeiwaki
2
16k
puppeteer-ruby: Ruby/Railsのためのブラウザオートメーションツール
yusukeiwaki
0
1.8k
Other Decks in Technology
See All in Technology
文字起こし基盤の信頼性
abnoumaru
0
120
2026年のソフトウェア開発を考える(2026/07版) / Agentic Software Engineering 2026-07 Findy Edition
twada
PRO
26
11k
仕様駆動開発、導入半年。「本当に速くなってるの?」にデータで答える / AICon2026_hirakawa
rakus_dev
0
320
なぜ、あなたのエージェントは言うことを聞かないのか
segavvy
1
380
穢れた技術選定について
watany
19
6.2k
それでも、技術なブログを書く理由 #kichijojipm / Why I Still Write Tech Blogs Even Now
shinkufencer
0
480
Alphaモジュール使っていいのかい!?いけないのかい!?どっちなんだいっ!?
watany
1
320
変更し続けられるシステムをどう保つか — AI時代のSSoTという設計原則
kawauso
1
1.1k
Type-safe IaC for Dart
coborinai
0
180
GoでCコンパイラを作った話
repunit
0
150
ゴールデンパスは敷いただけでは道にならない ─ 企画部門のエンジニアが技術標準を事業価値に変えるまで
mhrtech
1
260
10年目を迎えた「ABEMA」がどのように AI 活用を推進して、AI 駆動開発にシフトしているのか / How ABEMA, entering its 10th year, is promoting the use of AI and shifting toward AI-driven development
miyukki
0
370
Featured
See All Featured
Into the Great Unknown - MozCon
thekraken
41
2.6k
How GitHub (no longer) Works
holman
316
150k
The agentic SEO stack - context over prompts
schlessera
0
850
Leveraging Curiosity to Care for An Aging Population
cassininazir
1
420
Abbi's Birthday
coloredviolet
3
8.8k
Exploring the relationship between traditional SERPs and Gen AI search
raygrieselhuber
PRO
2
4.2k
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
1.1k
職位にかかわらず全員がリーダーシップを発揮するチーム作り / Building a team where everyone can demonstrate leadership regardless of position
madoxten
64
56k
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
590
Applied NLP in the Age of Generative AI
inesmontani
PRO
4
2.4k
The World Runs on Bad Software
bkeepers
PRO
72
12k
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
190
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