Ruby Concurrency

51
or Concurrency Hell How I stopped worrying about it Egor Hamaliy

Transcript of Ruby Concurrency

Page 1: Ruby Concurrency

or

Concurrency Hell

How I stopped worrying about it

Egor Hamaliy

Page 2: Ruby Concurrency

Agenda

1. Concurrency and Parallelism

2. General Concepts

3. Models

Page 3: Ruby Concurrency
Page 4: Ruby Concurrency

• Actors

• Mutexes/Locks

• STM

• CSP

• Futures/Promises

• …

Models

Page 5: Ruby Concurrency

Models

• Coroutines

• Evented IO• Process calculi• Petri nets• ...

Page 6: Ruby Concurrency
Page 7: Ruby Concurrency

GENERAL CONCEPTS

Concurrency/Parallelism

OS mechanism

Scheduling

Communication

Part #1

Page 8: Ruby Concurrency

Concurrency vs Parallelism

What’s the difference ?

Page 9: Ruby Concurrency

Not all programmers agree on the meaning of the

terms 'parallelism' and 'concurrency'. They may

define them in different ways or do not distinguishthem at all.

Page 10: Ruby Concurrency

Rob Pike

Page 11: Ruby Concurrency

Concurrency is about dealing with lots of things at

once.

Parallelism is about doing lots of things at once.

http://blog.golang.org/concurrency-is-not-parallelism

Rob Pike

Page 12: Ruby Concurrency
Page 13: Ruby Concurrency
Page 14: Ruby Concurrency

Execution

How things are executed?

Page 15: Ruby Concurrency

• Process

• Thread

• Green Thread

OS Primitives

Page 16: Ruby Concurrency

Scheduling

How things are scheduled?

Page 17: Ruby Concurrency

Preemptive

Page 18: Ruby Concurrency

Cooperative

Page 19: Ruby Concurrency

Communication

How do the executing things not trip over each other?

Page 20: Ruby Concurrency

Communication is always HARD

Page 21: Ruby Concurrency

Models

Threads/Mutexes

Transactional Memory

Processes & IPC

CSP

Evented/Coroutines

Actors

Part #2

Page 22: Ruby Concurrency

Model Execution Scheduling Communication Concurrent/Parallel

Implementation

Mutexes Threads Preemptive Shared Memory(locks) C/P Mutex

Transactional

Memory

Threads Preemptive Shared memory(commit/abort) C/P Clojure STM

Processes &

IPC

Processes Preemptive Shared memory/Message

passing

C/P Resque/Forking

CSP Threads/Proc

esses

Preemptive Message passing(channels) C/P Golang

Actors Threads Preemptive Message passing(mailboxes) C/P Erlang/Celluloid

Futures &

Promises

Threads Cooperative Message passing(itself) C/P Oz/Celluloid

Coroutines 1

process/threa

d

Cooperative Message passing C Fibers

Evented 1

process/threa

d

Cooperative Shared memory C Eventmachine

Page 23: Ruby Concurrency

Atomicity problems

Page 24: Ruby Concurrency

Mutex

Page 25: Ruby Concurrency

Pros

• No need to worry about scheduling (preemptive)

• Commonly used

• Wide language support

Cons

• Scheduling overhead (context switching)

• Synchronization/locking issues

Mutex

Page 26: Ruby Concurrency

http://en.wikipedia.org/wiki/Software_transactional_memory

"After completing an entire transaction verifies that other

threads have not made changes to memory that it

accessed in the past...If validation is successful, made

permanent, is called a commit."

"May also abort at any time."

Transactional Memory

Page 27: Ruby Concurrency

Thread1:

atomic {

- read variable

- increment variable

- write variable

}

Thread2:

atomic {

- read variable

- increment variable

# going to write, but Thread1 has written variable...

# notices Thread1 changed data, so ROLLS BACK

- write variable

}

“Don't wait on a lock, just check when we're ready to commit”

Transactional Memory

Page 28: Ruby Concurrency

Transactional Memory

Page 29: Ruby Concurrency

Pros

• Increased concurrency

• No thread needs to wait for access to a resource

• Smaller scope that needs synchronizing - modifying disjoint parts of a

data structure

STM's benefits

http://www.haskell.org/haskellwiki/Software_transactional_memory

Cons

• Aborting transactions

• Places limitations on the behavior of transactions - they cannot perform

any operation that cannot be undone, including most I/O.

Transactional Memory

Page 30: Ruby Concurrency

Methods of IPC

• Pipes

• Shared memory

• Message queues

IPC

Page 31: Ruby Concurrency

How do we handle atomicity? Don't share memory.

How to communicate?

IPC

Page 32: Ruby Concurrency

Pros

• Can't corrupt data when data is not shared.

• No locking.

• Easier to scale horizontally (adding nodes).

Cons

• Can't communicate over shared memory

• Slower to spawn a new process

• More memory overhead.

• Scaling horizontally is expensive.

IPC

Page 33: Ruby Concurrency

Communicating Sequential Processes

CSP

Page 34: Ruby Concurrency

Pros

• Uses message passing and channels heavily, alternative to

locks

Cons

• Handling very big messages, or a lot of messages,

unbounded buffers

• Messaging is essentially a copy of shared

CSP

Page 35: Ruby Concurrency

Actors

Page 36: Ruby Concurrency

Atomicity? Conflict? Every actor has it's own address space.

Don't share memory. Communicate via mailboxes.

Actors

Page 37: Ruby Concurrency

Comparison with CSP

• CSP processes are anonymous, while actors have

identities.

• Message-passing in actor systems is fundamentally

asynchronous (CSP traditionally uses synchronous

messaging: "rendezvous")

• CSP uses explicit channels for message passing,

whereas actor systems transmit messages to named

destination actors.

Actors

Page 38: Ruby Concurrency

Pros

• Uses message passing and channels heavily

• No shared state (avoid locks, easier to scale)

• Easier to maintain the code

Cons

• When shared state is required doesn't fit as well

• Handling very big messages, or a lot of messages

• Messaging is essentially a copy of shared data

Actors

Page 39: Ruby Concurrency

Fibers

Page 40: Ruby Concurrency

Fibers are coroutines:

Cooperative! Handing execution rights between one

another, saving local state.

Fibers

Page 41: Ruby Concurrency

A Curious Course on Coroutines and Concurrency:

David Beazley (https://twitter.com/dabeaz) writing an operating system

with only coroutines.

http://dabeaz.com/coroutines/

No Threads, Evented style, just cooperative scheduling of coroutines...

Possible use cases:

http://stackoverflow.com/questions/303760/what-are-use-cases-for-a-

coroutine

Fibers

Page 42: Ruby Concurrency

Pros

• Expressive state: state based computations much easier

to understand and implement

• No need for locks (cooperative scheduling)

• Scales vertically (add more cpu)

Cons

• Single thread: Harder to parallelize/scale horizontally

(use more cores, add more nodes)

• Constrained to have all the components work together

symbiotically

Fibers

Page 43: Ruby Concurrency

Eventmachine

Page 44: Ruby Concurrency

Examples

• C10k problem

• Eventmachine in ruby

• Twisted in python

• Redis's event loop

• Apache vs Nginx

• Node.js vs the world

Eventmachine

Page 45: Ruby Concurrency

Eventmachine

“Evented servers are really good for very light requests, but

if you have a long-running request, it falls down on its face”

Technically, valid, but in practice, not necessarily true.

Page 46: Ruby Concurrency

Eventmachine

Reactor:

• wait for event (Reactor job)

• dispatch "Ready-to-Read" event to user handler (Reactor job)

• read data (user handler job)

• process data ( user handler job)

Proactor:

• wait for event (Proactor job)

• read data (now Proactor job)

• dispatch "Read-Completed" event to user handler (Proactor job)

• process data (user handler job)

Page 47: Ruby Concurrency

Pros

• Avoid polling. CPU bound vs IO bound

• Expanding your horizons (very different paradigms)

• Scales well vs spawning many threads

Cons

• You block the event loop, all goes bad

• Program flow is "spaghetti"-ish

• Callback Hell

• Hard to debug, you loose "the stack”

Eventmachine

Page 48: Ruby Concurrency

Sidenote: C10M

http://highscalability.com/blog/2013/5/13/the-secret-to-10-million-concurrent-connections-the-kernel-i.html

http://c10m.robertgraham.com/p/manifesto.html

http://c10m.robertgraham.com/2013/02/wimpy-cores-and-scale.html

Page 49: Ruby Concurrency

Conclusion

Page 50: Ruby Concurrency

USE THE BEST TOOL FOR THE JOB

Page 51: Ruby Concurrency

Questions?