EventMachine: The Speed Demon

Post on 19-Jun-2015

1.248 views 2 download

Tags:

description

EventMachine presentation from RailsConf 2010

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

QUESTIONS?Aman Gupta

@tmm1http://scribd.com/tmm1