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
Cooperative Multitasking with Twisted: Getting ...
Search
David Reid
February 01, 2012
Programming
1
770
Cooperative Multitasking with Twisted: Getting Things Done Concurrently
David Reid
February 01, 2012
Tweet
Share
Other Decks in Programming
See All in Programming
フロントエンド開発のためのブラウザ組み込みAI入門
masashi
6
3.2k
Devoxx BE - Local Development in the AI Era
kdubois
0
130
なぜGoのジェネリクスはこの形なのか? - Featherweight Goが明かす設計の核心
qualiarts
0
190
なぜあの開発者はDevRelに伴走し続けるのか / Why Does That Developer Keep Running Alongside DevRel?
nrslib
3
410
CSC509 Lecture 04
javiergs
PRO
0
300
AI駆動で0→1をやって見えた光と伸びしろ
passion0102
1
640
AI Coding Meetup #3 - 導入セッション / ai-coding-meetup-3
izumin5210
0
3.4k
Domain-centric? Why Hexagonal, Onion, and Clean Architecture Are Answers to the Wrong Question
olivergierke
3
930
『毎日の移動』を支えるGoバックエンド内製開発
yutautsugi
2
270
bootcamp2025_バックエンド研修_WebAPIサーバ作成.pdf
geniee_inc
0
120
TransformerからMCPまで(現代AIを理解するための羅針盤)
mickey_kubo
1
140
ソフトウェア設計の実践的な考え方
masuda220
PRO
4
620
Featured
See All Featured
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
140
34k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
253
22k
Practical Orchestrator
shlominoach
190
11k
Stop Working from a Prison Cell
hatefulcrawdad
271
21k
Unsuck your backbone
ammeep
671
58k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
5.6k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
9
990
ReactJS: Keep Simple. Everything can be a component!
pedronauck
667
120k
Context Engineering - Making Every Token Count
addyosmani
7
270
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
36
6.1k
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.2k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.2k
Transcript
Cooperative Multitasking with Twisted “Getting Things Done Concurrently” David Reid
<
[email protected]
>
Alternate Title
Alternate Title How I learned to stop worrying (about threads)
and use timed events to yield to the reactor so that synchronous tasks can cooperate with each other in a single thread.
Cooperative Multitasking
Cooperative Multitasking
Cooperative Multitasking
Cooperative Multitasking
Cooperative Multitasking
Cooperative Multitasking
Things will block
Fine in moderation
So what blocks?
Non-twisted networking
Non-twisted networking urllib & httplib smtplib python-memcached
Non-twisted networking twisted.web.client twisted.mail.smtp twisted.protocols.memcache
C Extensions
C Extensions DB-APIs: psycopg2, sqlite Hard math: PyCrypto socket.gethostbyname
C Extensions twisted.enterprise deferToThread deferToThread/twisted.names
File I/O
File I/O Yeah ... pretty much all of it.
The for loop.
def do_stuff(data): for x in data: do_work(x)
def do_stuff(data): for x in data: do_work(x)
Next: Introducing Twisted in 3 slides.
while true: stuff = wait_for_stuff(timeout) if stuff: check_reads_and_writes() run_timed_events() The
Reactor: Approximately
while true: stuff = wait_for_stuff(timeout) if stuff: check_reads_and_writes() run_timed_events() The
Reactor: Approximately
while true: stuff = wait_for_stuff(timeout) if stuff: check_reads_and_writes() run_timed_events() The
Reactor: Approximately
while true: stuff = wait_for_stuff(timeout) if stuff: check_reads_and_writes() run_timed_events() The
Reactor: Approximately
Deferreds Data Source result or failure Deferred
Deferreds Data Source result or failure Deferred res
Deferreds Data Source result or failure Deferred err
Deferreds Data Source result or failure Deferred
Deferreds Data Source result or failure Deferred err
Deferreds Data Source result or failure Deferred res
reactor.callLater
reactor.callLater reactor.callLater(10, do_stuff)
reactor.callLater reactor.callLater(0.001, do_stuff)
def do_stuff(data): d = Deferred() def do_later(): do_work(data.pop()) if not
data: d.callback(True) else: reactor.callLater(0.1, do_later) reactor.callLater(0.1, do_later) return d
def do_stuff(data): d = Deferred() def do_later(): do_work(data.pop()) if not
data: d.callback(True) else: reactor.callLater(0.1, do_later) reactor.callLater(0.1, do_later) return d
def do_stuff(data): d = Deferred() def do_later(): do_work(data.pop()) if not
data: d.callback(True) else: reactor.callLater(0.1, do_later) reactor.callLater(0.1, do_later) return d
def do_stuff(data): d = Deferred() def do_later(): do_work(data.pop()) if not
data: d.callback(True) else: reactor.callLater(0.1, do_later) reactor.callLater(0.1, do_later) return d
def do_stuff(data): d = Deferred() def do_later(): do_work(data.pop()) if not
data: d.callback(True) else: reactor.callLater(0.1, do_later) reactor.callLater(0.1, do_later) return d
def do_stuff(data): d = Deferred() def do_later(): do_work(data.pop()) if not
data: d.callback(True) else: reactor.callLater(0.1, do_later) reactor.callLater(0.1, do_later) return d
def do_stuff(data): d = Deferred() def do_later(): do_work(data.pop()) if not
data: d.callback(True) else: reactor.callLater(0.1, do_later) reactor.callLater(0.1, do_later) return d
def do_stuff(data): d = Deferred() def do_later(): do_work(data.pop()) if not
data: d.callback(True) else: reactor.callLater(0.1, do_later) reactor.callLater(0.1, do_later) return d
twisted.internet.task.Cooperator
twisted.internet.task.Cooperator twisted.internet.task.coiterate
twisted.internet.task.Cooperator twisted.internet.task.coiterate twisted.internet.task.cooperate
def do_stuff(data): def doterator(): for x in data: do_work(x) yield
None return coiterate(doterator())
def do_stuff(data): def doterator(): for x in data: do_work(x) yield
None return coiterate(doterator())
def do_stuff(data): def doterator(): for x in data: do_work(x) yield
None return coiterate(doterator())
def do_stuff(data): def doterator(): for x in data: do_work(x) yield
None return coiterate(doterator())
def do_stuff(data): def doterator(): for x in data: do_work(x) yield
None return coiterate(doterator())
• Similar to coiterate • Returns a CooperativeTask instead of
a Deferred cooperate
def do_stuff(data): def doterator(): for x in data: do_work(x) yield
None return cooperate(doterator())
def do_stuff(data): def doterator(): for x in data: do_work(x) yield
None return cooperate(doterator())
def do_stuff(data): def doterator(): for x in data: do_work(x) yield
None return cooperate(doterator())
def do_stuff(data): def doterator(): for x in data: do_work(x) yield
None return cooperate(doterator())
def do_stuff(data): def doterator(): for x in data: do_work(x) yield
None return cooperate(doterator()) task = do_stuff(someData) task_d = task.whenDone() task.pause() task.resume() task.stop()
def do_stuff(data): def doterator(): for x in data: do_work(x) yield
None return cooperate(doterator()) task = do_stuff(someData) task_d = task.whenDone() task.pause() task.resume() task.stop()
def do_stuff(data): def doterator(): for x in data: do_work(x) yield
None return cooperate(doterator()) task = do_stuff(someData) task_d = task.whenDone() task.pause() task.resume() task.stop()
def do_stuff(data): def doterator(): for x in data: do_work(x) yield
None return cooperate(doterator()) task = do_stuff(someData) task_d = task.whenDone() task.pause() task.resume() task.stop()
def do_stuff(data): def doterator(): for x in data: do_work(x) yield
None return cooperate(doterator()) task = do_stuff(someData) task_d = task.whenDone() task.pause() task.resume() task.stop()
def do_stuff(data): def doterator(): for x in data: do_work(x) yield
None return cooperate(doterator()) task = do_stuff(someData) task_d = task.whenDone() task.pause() task.resume() task.stop()
def do_stuff(data): def doterator(): for x in data: do_work(x) yield
None return cooperate(doterator()) task = do_stuff(someData) task_d = task.whenDone() task.pause() task.resume() task.stop()
• Your code is going to block. • Iterating over
stuff is a big place where synchronous code blocks for unacceptable periods of time. • Iterating is easily broken up by timed events. • Twisted comes with APIs for making this easy. • These APIs are the building blocks for your ideal task system.
Questions (Mine, not yours.)
Why?
Why? Being able to do more stuff is sometimes more
important than doing stuff quickly. * * Making a single user’s request 10ms faster is great, but not if you can only handle 1 request at a time.
Why call later instead of next iteration?
Why call later instead of next iteration? Timed events are
more flexible and you need them anyway.
Can’t I just use deferToThread for python code?
Can’t I just use deferToThread for python code? Yes, but
the GIL hates you.
Can’t I just use deferToThread for python code? Yes, but
the GIL hates you. It’s OK, it hates me too.
Can’t I just run code in a separate processes?
Can’t I just run code in a separate processes? Yes,
look at Ampoule.
Can’t I just run code in a separate processes? Yes,
look at Ampoule. But you probably want those processes to do more than one thing too.
This isn’t appropriate for my situation at all.
This isn’t appropriate for my situation at all. So don’t
do it.
This isn’t appropriate for my situation at all. So don’t
do it. Seriously.
SERIOUSLY.
• Twisted (http://twistedmatrix.com) • Ampoule (https://launchpad.net/ampoule) • txRDQ (https://launchpad.net/txrdq) •
Mochi Media (WE’RE HIRING) • http://mochimedia.com • http://bit.ly/mochi-jobs References