+ All Categories
Home > Documents > Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes...

Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes...

Date post: 20-Dec-2020
Category:
Upload: others
View: 3 times
Download: 0 times
Share this document with a friend
69
Concurrency: Rubies, Plural Elise Huard & Eleanor McHugh RubyConf 2010
Transcript
Page 1: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

Concurrency: Rubies, Plural

Elise Huard & Eleanor McHugh

RubyConf 2010

Page 2: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

manifestoconcurrency matters

Page 3: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

multicoreit’s a revolution in mainstream computing

and you want to exploit it in Ruby

Page 4: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

MULTIPROCESSOR/MULTICORE

Page 5: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

NETWORK ON CHIP(50..96..100 CORES)

Page 6: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

diminishing returns

• communication takes finite time

• so doubling processors never doubles a system’s realworld performance

• realtime capacity ~70% theoretical capacity

• or less!!!

• independence = performance

Page 7: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

“... for the first time in history, no one is building a much faster sequential processor. If you want your programs to run significantly faster (...) you’re going to have to parallelize your program.”

Hennessy and Patterson “Computer Architectures” (4th edition, 2007)

Page 8: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

concurrencywhy it really matters

Page 9: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

an aide to good design

• decouples independent tasks

• encourages data to flow efficiently

• supports parallel execution

• enhances scalability

• improves program comprehensibility

Page 10: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance
Page 11: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance
Page 12: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance
Page 13: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

finding green pasturesadopting concurrency idioms from other languages

Page 14: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

victims of choice

Erlang Actors

Go Concurrent Sequential Processes

Clojure Software Transactional Memory

Icon Coexpressions

Page 15: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

coroutinessynchronising via transfer of control

Page 16: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

icon

• a procedural language

• with a single thread of execution

• generators are decoupled coexpressions

• and goal-directed evaluation

• creates flexible flow-of-control

Page 17: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

icon coexpressionsprocedure main()

n := create(seq(1)\10) s := create(squares())c := create(cubes())while write(@n, “\t”, @s, “\t”, @c)

end

procedure seq(start)repeat {

suspend startstart += 1

}end

procedure squares()odds := 3sum := 1repeat {

suspend sum sum +:= oddsodds +:= 2

}end

procedure cubes()odds := 1sum := 1i := create(seq(2))repeat {

suspend sum sum +:= 1 + (odds * 6)odds +:= @i

}end

1 1 1

2 4 8

3 9 27

4 16 64

5 25 125

6 36 216

7 49 343

8 64 512

9 81 729

10 100 1000

Page 18: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

ruby fibers

• coexpressions

• bound to a single thread

• scheduled cooperatively

• the basis for enumerators

• library support for full coroutines

Page 19: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

ruby coexpressionsdef seq start = 1

Fiber.new do loop do

Fiber.yield start start += 1

endend

end

n = seq()

s = Fiber.new dosum, odds = 1, 3loop do

Fiber.yield sum sum += oddsodds += 2

endend

c = Fiber.new dosum, odds, i = 1, 1, seq(2)loop do

Fiber.yield sum sum += 1 + (odds * 6)odds += i.resume

endend

10.times doputs “#{n.resume}\t#{s.resume}\t#{c.resume}”

end

1 1 1

2 4 8

3 9 27

4 16 64

5 25 125

6 36 216

7 49 343

8 64 512

9 81 729

10 100 1000

Page 20: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

ruby coroutinesrequire 'fiber'

def login Fiber.new do |server, name, password| puts "#{server.transfer(Fiber.current)} #{name}" puts "#{server.transfer name} #{password}" puts “login #{server.transfer password}” endend

def authenticate Fiber.new do |client| name = client.transfer "name:" password = client.transfer "password:" if password == "ultrasecret" then client.transfer "succeeded" else client.transfer "failed" end endend

login.transfer authenticate, "jane doe", "ultrasecret"login.transfer authenticate, "john doe", "notsosecret"

name: jane doepassword: ultrasecretlogin succeededname: john doepassword: notsosecretlogin failed

Page 21: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

icon revisitedprocedure powers()

repeat {while e := get(queue) do

write(e, “\t”, e^ 2, “\t”, e^ 3)e @&source

}end

procedure process(L)consumer := get(L) every producer := !L do

while put(queue, @producer) doif *queue > 3 then @consumer

@consumer end

global queue

procedure main()queue := []process{ powers(), 1 to 5, seq(6, 1)\5 }

end

1 1 1

2 4 8

3 9 27

4 16 64

5 25 125

6 36 216

7 49 343

8 64 512

9 81 729

10 100 1000

Page 22: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

a ruby equivalentrequire 'fiber'

def process consumer, *fibersq = consumer.transfer(Fiber.current)fibers.each do |fiber|

while fiber.alive?q.push(fiber.resume)q = consumer.transfer(q) if q.length > 3

endendconsumer.transfer q

end

powers = Fiber.new do |caller|loop do

caller.transfer([]).each do |e|puts "#{e}\t#{e ** 2}\t#{e ** 3}" rescue nil

endend

end

low_seq = Fiber.new do5.times { |i| Fiber.yield i + 1 }nil

end

high_seq = Fiber.new do(6..10).each { |i| Fiber.yield i }

end

process powers, low_seq, high_seq

1 1 1

2 4 8

3 9 27

4 16 64

5 25 125

6 36 216

7 49 343

8 64 512

9 81 729

10 100 1000

Page 23: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

processesthe traditional approach to concurrency

Page 24: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

language VM

OS(kernel processes, other processes)

Your program

multicore - multiCPU

Page 25: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

processes + threads

Process 2

RAMmemory space

Process 1

thread1

scheduler (OS)

CPU CPU

memory space

thread2 t1 t2 t3

Page 26: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

cooperative preemptive

active task has full control scheduler controls task activity

runs until it yields control switches tasks automatically

scheduler activates new task a task can still yield control

blocking I/O blocks the system blocking I/O blocks the task

Classic MacOS MacOS X

schedulers

Page 27: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

3 threads, 2 cores

1

2

3

1

1

2

3 1

23

core1 core2 core1 core2

Page 28: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

process thread

address space private shared

kernel resources private + shared shared

scheduling kernel varies

communication IPC via kernel in process

control children in process

feature comparison

Page 29: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

process creation

• unix spawns

• windows cuts from whole cloth

• ruby wraps this many ways

• but we’re mostly interested in fork

Page 30: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

pipes

• creates an I/O channel between processes

• unnamed pipes join two related processes

• posix named pipes

• live in the file system

• have user permissions

Page 31: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

def execute &blockchild_input, parent_input = IO.pipepid = fork dochild_input.closeresult = block.callparent_input.write result.to_jsonparent_input.close

endparent_input.closesorted = JSON.parse child_input.readchild_input.closeProcess.waitpid pidreturn sorted

end

forking

Page 32: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

context switchingOperating System Benchmark Operation Time (ms)

Linux

spawn new process fork() / exec() 6.000

clone current process fork() 1.000

spawn new thread pthread_create 0.300

switch current process sched_yield() 0.019

switch current thread sched_yield() 0.019

Windows NT

spawn new process spawnl() 12.000

clone current process N/A ---

spawn new thread pthread_create() 0.900

switch current process Sleep(0) 0.010

switch current thread Sleep(0) 0.006

C Benchmarks by Gregory Travis on a P200 MMXhttp://cs.nmu.edu/~randy/Research/Papers/Scheduler/

Page 33: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

fork

• exploit OS’s efficiency in spawning processes

• ruby enterprise = patched for COW

• not on Ruby 1.9 (yet)

Page 34: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

persistent pipesprocess 1

File.umask 0 MKFIFO = 132syscall MKFIFO, fifo_name, 0666fd = IO.sysopen “server”, File::RDONLYserver = File.new fd, "r"client_name = server.gets.chompputs "#{Time.now}: [#{client_name}]"fd = IO.sysopen client_name, File::WRONLYclient = IO.new fd, "w"message = server.gets.chompclient.puts message.reverseclient.closeserver.closeFile.delete “server”

process 2

File.umask 0 MKFIFO = 132syscall MKFIFO, “client”, 0666fd = IO.sysopen "server", File::WRONLYserver = IO.new fd, "w"server.puts fifo_nameserver.puts "hello world!"server.closefd = IO.sysopen “client”, File::RDONLYclient = IO.new fd, "r"puts client.getsclient.closeFile.delete “client”

Page 35: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

shared state hurts

• non-determinism

• atomicity

• fairness/starvation

• race conditions

• locking

• transactional memory

Page 36: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

semaphores

• exist independently of processes

• provide blocking access

• allowing processes to be synchronised

• nodes in the file system

• usable from Ruby with syscall

Page 37: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

synchronising processesrequire ‘dl’require ‘fcntl’libc = DL::dlopen ‘libc.dylib’ open = libc[‘sem_open’, ‘ISII’]try_wait = libc[‘sem_trywait’, ‘II’]wait = libc[‘sem_wait’, ‘II’]post = libc[‘sem_post’, ‘II’]close = libc[‘sem_close’, ‘II’]

process 1s = open.call(“/tmp/s”, Fcntl::O_CREAT, 1911)[0]wait.call sputs “locked at #{Time.now}”sleep 50puts “posted at #{Time.now}”post.call sclose.call s

process 2s = open.call(“/tmp/s”)t = Time.nowif try_wait.call(s)[0] == 0 then

puts “locked at #{t}”else

puts “busy at #{t}”wait.call sputs “waited #{Time.now - t} seconds”

end

locked at Thu May 28 01:03:23 +0100 2009 busy at Thu May 28 01:03:36 +0100 2009posted at Thu May 28 01:04:13 +0100 2009 waited 47.056508 seconds

Page 38: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

complexity

• file locking

• shared memory

• message queues

• transactional data stores

Page 39: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

threadsthe popular approach to concurrency

Page 40: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

threads under the hood

from http://www.igvita.com/2008/11/13/concurrency-is-a-myth-in-ruby/ @igrigorik

Page 41: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

the global lockdown

• compatibility for 1.8 C extensions

• only one thread executes at a time

• scheduled fairly with a timer thread

• 10 μs for Linux

• 10 ms for Windows

Page 42: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

the macruby twist

• grand central despatch

• uses an optimal number of threads

• state is shared but not mutable

• object-level queues for atomic mutability

Page 43: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

synchronisation

• locks address race conditions

• mutex

• condition variable

• monitor

• deadlocks

• livelocks

Page 44: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

RUBY THREADSrequire 'thread'threads = []account = UnsafeAccount.newmutex = Mutex.new10.times dothreads << Thread.new domutex.synchronize doaccount.receive 10

endend

end

threads.each {|t| t.join }

puts account.balance

Page 45: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

THREADS + SOCKETSrequire 'socket'require 'thread'require 'mutex_m'

class UDPServerinclude Mutex_m

def start address, port, *options@socket = [email protected] address, [email protected] *optionsevent_loop

end

def [email protected]@socket = nilunlock

end

def serve request["hello", 0]

end

private

def event_looploop do

if sockets = select([@socket]) thensockets[0].each do |s|

spawn_handler send

endend

endend

def spawn_handler sockett = Thread.new(socket) do |s|

message, peer = *s.recvfrom 512reply, status = *serve messageUDPSocket.open.send reply, status, peer[2], peer[1]

endt.join

end

Page 46: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

clojure

lisp dialect for the JVM

refs software transactional memory

agents independent, asynchronous change

vars in-thread mutability

check out Tim Bray’s Concur.next series

Page 47: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

parallel banking(ns account)

  ; ref  (def transactional-balance (ref 0))

  ; transfer: within a transaction  (defn parallel-transfer [amount]     (dosync        (alter transactional-balance transfer amount)))

  ; many threads adding 10 onto account  (defn parallel-stm [amount nthreads]     (let [threads (for [x (range 0 nthreads)] (Thread. #(parallel-transfer amount)))]        (do           (doall (map #(.start %) threads))           (doall (map #(.join %) threads))))     @transactional-balance)

Page 48: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

ruby can do that toorequire 'clojure'

include Clojure

def parallel_transfer(amount)  Ref.dosync do    @balance.alter {|b| b + amount }  endend

def parallel_stm(amount, nthreads)  threads = []  10.times do    threads << Thread.new do      parallel_transfer(amount)    end  end  threads.each {|t| t.join }  @balance.derefend

@balance = Ref.new(0)puts parallel_stm(10,10)

Page 49: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

enumerableseveryday ruby code is often naturally concurrent

Page 50: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

map/reduce

• decompose into independent elements

• process each element separately

• use functional code with side-effects

• recombine the elements

• intrinsically suited to parallel execution

Page 51: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

a two-phase operationconcurrent sequential

(0..5).to_a.each { |i| puts i }

x = 0(0..5).to_a.each { |i| x = x + i }

(0..5).to_a.map { |i| i ** 2 }

(0..5).to_a.inject { |sum, i| sum + i }

Page 52: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

the parallel gemrequire 'brute_force'require 'parallel'

# can be run with :in_processes as wellmapped = Parallel.map((0..3).to_a, :in_threads => 4) do |num|  map("english.#{num}") # hash the whole dictionaryend

hashed = "71aa27d3bf313edf99f4302a65e4c042"

puts reduce(hashed, mapped) # returns “zoned”

Page 53: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

TECHNIQUES

• event-driven I/O

Page 54: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

algebra, actors + eventssynchronising concurrency via communication

Page 55: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

process calculi

• mathematical model of interaction

• processes and events

• (a)synchronous message passing

• named channels with atomic semantics

Page 56: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

go

• statically-typed compiled systems language

• class-free object-orientation

• garbage collection

• independent lightweight coroutines

• implicit cross-thread scheduling

Page 57: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

package mainimport "syscall"

func (c *Clock) Start() {if !c.active {

go func() {c.active = truefor i := int64(0); ; i++ {

select {case status := <- c.Control:

c.active = statusdefault:

if c.active {c.Count <- i

}syscall.Sleep(c.Period)

}}

}()}

}

type Clock struct {Period int64Count chan int64Control chan boolactive bool

}

func main() {c := Clock{1000, make(chan int64), make(chan bool), false}c.Start()

for i := 0; i < 3; i++ {println("pulse value", <-c.Count, "from clock")

}

println("disabling clock")c.Control <- falsesyscall.Sleep(1000000)println("restarting clock")c.Control <- trueprintln("pulse value", <-c.Count, "from clock")

}

produces: pulse value 0 from clock pulse value 1 from clock pulse value 2 from clock disabling clock restarting clock pulse value 106 from clock

a signal generator

Page 58: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

RUBY SIGNAL GENERATOR

Page 59: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

actor model

• named actors: no shared state

• asynchronous message passing (fire and forget)

Page 60: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

erlang

• Actor model: Actors, asynchronous message passing

• actors = “green processes”

• efficient VM (SMP enabled since R12B)

• high reliability

© ericsson 2007

Text

Page 61: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

erlang-module(brute_force).-import(plists).-export(run/2).

map(FileName) ->    {ok, Binary} = file:read_file(FileName),    Lines = string:tokens(erlang:binary_to_list(Binary), "\n"),    lists:map(fun(I) -> {erlang:md5(I), I} end, Lines).

reduce(Hashed, Dictionary) ->    dict:fetch(Hashed, Dictionary).

run(Hashed, Files) ->    Mapped = plists:map(fun(I) -> map(I) end, Files),    Values = lists:flatten(Mapped),    Dict = dict:from_list(Values),    reduce(Hashed, Dict).

Page 62: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

rubinius: actors

• actors in the language: threads with inbox

• (VM actors to communicate between actors in different VMs)

Page 63: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

rubinius actorsrequire 'quick_sort'require 'actor'

class RbxActorSort

def execute(&block)current = Actor.currentActor.spawn(current) {|current|

current.send(block.call) }Actor.receive

end

end

puts q = QuickSort.new([1,7,3,2,77,23,4,2,90,100,33,2,4], RbxActorSort).sort

Page 64: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

ruby: revactor

• erlang-like semantics: actor spawn/receive, filter

• Fibers (so cooperative scheduling)

• Revactor::TCP for non-blocking network access (1.9.2) (rev eventloop)

Page 65: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

ruby: futuresLazy.rb gem (@mentalguy)require 'lazy'require 'lazy/futures'

def fib(n)  return n if (0..1).include? n  fib(n-1) + fib(n-2) if n > 1end

puts "before first future"future1 = Lazy::Future.new { fib(40) }puts "before second future"future2 = Lazy::Future.new { fib(40) }puts "and now we're waiting for results ... getting futures fulfilled is blocking"

puts future1puts future2

Page 66: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

kernel stuff

Some of these problems have been solved before ...

Page 67: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

GOLDEN RULES

• beware of shared mutable state

• but: sane ways to handle concurrency

• they are all possible in Ruby

Page 68: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

fun

Page 69: Concurrency: Rubies, Plural · 2015. 10. 20. · diminishing returns • communication takes finite time • so doubling processors never doubles a system’s realworld performance

http://www.delicious.com/elisehuard/concurrency

http://www.ecst.csuchico.edu/~beej/guide/ipc/

http://wiki.netbsd.se/kqueue_tutorial

http://www.kegel.com/c10k.html

Elise Huard @elise_huard http://jabberwocky.eu

Eleanor McHugh @feyeleanor http://slides.games-with-brains.net

Further Reading


Recommended