Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Cooperative Multitasking with Twisted: Getting Things Done Concurrently

David Reid
February 01, 2012

Cooperative Multitasking with Twisted: Getting Things Done Concurrently

David Reid

February 01, 2012
Tweet

Other Decks in Programming

Transcript

  1. 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.
  2. 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
  3. 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
  4. 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
  5. 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
  6. 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
  7. 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
  8. 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
  9. 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
  10. 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()
  11. 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()
  12. 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()
  13. 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()
  14. 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()
  15. 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()
  16. 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()
  17. • 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.
  18. 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.
  19. Why call later instead of next iteration? Timed events are

    more flexible and you need them anyway.
  20. Can’t I just use deferToThread for python code? Yes, but

    the GIL hates you. It’s OK, it hates me too.
  21. 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.
  22. • 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