Distributed and concurrent programming with RabbitMQ and EventMachine Rails Underground 2009
EventMachine: The Speed Demon
-
Upload
aman-gupta -
Category
Documents
-
view
1.248 -
download
2
description
Transcript of EventMachine: The Speed Demon
EVENTMACHINEthe speed demon
Aman Gupta@tmm1
telnet 10.10.25.42 1337http://gist.github.com/329682
require 'rubygems'require 'eventmachine'
EM.run{
EM.run starts the reactor
Vattenfall (flickr)
EM.run takes over your process
EM.run does not return(until you call EM.stop)
EM.run{ puts 'reactor started!'}puts "this won't happen"
EM.run{ puts 'reactor started!' EM.stop}puts 'this will happen'
EM.run starts the reactor
EM.run starts the reactor
...reactor?
A reactor reacts to events
missjdub (flickr)
A reactor is a single-threaded while loop
(called the “reactor loop”)
while reactor_running? expired_timers.each{ |timer| timer.process } new_network_io.each{ |io| io.process }end
while reactor_running? sleep(100) 100_000.times{} while !do_check end # reactor loop is blocked!end
neoporcupine (flickr)
The reactor takes over your ruby process
The reactor takes over your ruby process
and invokes your callbacks on events
The reactor takes over your ruby process
and invokes your callbacks on events
...callbacks?
ret = operation()do_something_with(ret)
ret = operation()do_something_with(ret)
operation{ |ret| do_something_with(ret) }
vs
puts(1)1.times{ puts(2) }puts(3)
puts(1)1.times{ puts(2) }puts(3)
puts(1)operation{ puts(3) }puts(2)
vs
url = db.find_urlresponse = http.get(url)email.send(response)puts 'email sent'
url = db.find_urlresponse = http.get(url)email.send(response)puts 'email sent'
db.find_url{ |url| http.get(url){ |response| email.send(response){ puts 'email sent' } }}
vs
Balakov (flickr)
EM.start_server('0.0.0.0',1337, ChatClient)
Channel = EM::Channel.new
SnaPsi (flickr)
module ChatClient def post_init @name = "anonymous" @sid = Channel.subscribe do |msg| send_msg(msg) end
send_header send_prompt
Channel << "#{@name} has joined." endend
module ChatClient def post_init @name = "anonymous" @sid = Channel.subscribe do |msg| send_msg(msg) end
send_header send_prompt
Channel << "#{@name} has joined." endend
module ChatClient def post_init @name = "anonymous" @sid = Channel.subscribe do |msg| send_msg(msg) end
send_header send_prompt
Channel << "#{@name} has joined." endend
module ChatClient def post_init @name = "anonymous" @sid = Channel.subscribe do |msg| send_msg(msg) end
send_header send_prompt
Channel << "#{@name} has joined." endend
module ChatClient def post_init @name = "anonymous" @sid = Channel.subscribe do |msg| send_msg(msg) end
send_header send_prompt
Channel << "#{@name} has joined." endend
module ChatClient def unbind Channel.unsubscribe(@sid) Channel << "#{@name} has left." endend
module ChatClient def receive_data data @buf ||= '' @buf << data
while line = @buf.slice!(/(.+)\r?\n/) # ... end endend
module ChatClient def receive_data data @buf ||= '' @buf << data
while line = @buf.slice!(/(.+)\r?\n/) # ... end endend
...@buf?
rachel_thecat (flickr)
send_data(“hello”)send_data(“world”)
receive_data(“he”)receive_data(“llowo”)receive_data(“rld”)
network
while line = @buf.slice!(/(.+)\r?\n/) # ...end
brain_blogger (flickr)
if line =~ %r|^/me (.+)| Channel << "#{@name} #{$1.strip}"
elsif line =~ %r|^/nick (.+)| new_name = $1.strip[0..12] Channel << "#{@name} is #{new_name}" @name = new_name
elsif line =~ %r|^/quit| close_connection_after_writing
elsif line =~ %r|^/say (.+)| SayQueue.push "#{@name} said #{$1.strip}"
else Channel << "#{@name}: #{line}"end
SayQueue = EM::Queue.new
thowi (flickr)
q = EM::Queue.newq.pop{ |item| use(item) }
# process jobs by invoking `say`processor = proc{ |msg| EM.system("say", msg) do |out, status| # subprocess complete, pop another SayQueue.pop(&processor) end}
# pop the first item off the queueSayQueue.pop(&processor)
# process jobs by invoking `say`processor = proc{ |msg| EM.system("say", msg) do |out, status| # subprocess complete, pop another SayQueue.pop(&processor) end}
# pop the first item off the queueSayQueue.pop(&processor)
rtomazela (flickr)
# process jobs by invoking `say`processor = proc{ |msg| EM.system("say", msg) do |out, status| # subprocess complete, pop another SayQueue.pop(&processor) end}
# kick off the “recursive” procSayQueue.pop(&processor)
EM.system('ls'){ |output,status| if status.exitstatus == 0 puts output end}
EM.system('ls'){ |output,status| if status.exitstatus == 0 puts output end}
EM.popen 'ls', LsHandler
steve.grosbois (flickr)
EM::PeriodicTimer.new(90) do Channel << "The time is #{Time.now}"end
tveskov (flickr)
TwitterStream.new(%w[ railsconf eventmachine]) do |tweet| name = tweet[:user][:screen_name] msg = tweet[:text] Channel << "@#{name}: #{msg}"end
# gem install em-http-requestrequire 'em-http'
http = EM::HttpRequest.new( "http://stream.twitter.com/" + "filter.json?track=#{tags.join(',')}").get( :head => { 'authorization' => [user, pass] })
# gem install yajl-rubyrequire 'yajl'
parser = Yajl::Parser.newparser.on_parse_complete = blkhttp.stream do |data| parser << dataend
So what is EventMachine?
EventMachine is a reactor.
Vattenfall (flickr)
EventMachine is single threaded.
westpark (flickr)
EventMachine is a while loop.
gnislew (flickr)
EventMachine is all about concurrency.
meophamman (flickr)
pascal.charest (flickr)
EventMachine is for building web services.
$ gem install eventmachine
$ gem install eventmachine
rubinius
$ gem install eventmachine
rubiniusjruby
$ gem install eventmachine
rubiniusjruby
mri 1.8
$ gem install eventmachine
rubiniusjruby
mri 1.8yarv 1.9
Code: http://github.com/eventmachine/eventmachineGroup: http://groups.google.com/group/eventmachineRDoc: http://eventmachine.rubyforge.orgIRC: #eventmachine on irc.freenode.net
http://www.scribd.com/doc/28253878/EventMachine