Anda di halaman 1dari 86

EVENTMACHINE

the speed demon

Aman Gupta
@tmm1
telnet 10.10.25.42 1337
http://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)

vs

operation{ |ret| do_something_with(ret) }


puts(1)
1.times{ puts(2) }
puts(3)
puts(1)
1.times{ puts(2) }
puts(3)

vs

puts(1)
operation{ puts(3) }
puts(2)
url = db.find_url
response = http.get(url)
email.send(response)
puts 'email sent'
url = db.find_url
response = http.get(url)
email.send(response)
puts 'email sent'

vs
db.find_url{ |url|
http.get(url){ |response|
email.send(response){
puts 'email sent'
}
}
}
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."


end
end
module ChatClient
def post_init
@name = "anonymous"
@sid = Channel.subscribe do |msg|
send_msg(msg)
end

send_header
send_prompt

Channel << "#{@name} has joined."


end
end
module ChatClient
def post_init
@name = "anonymous"
@sid = Channel.subscribe do |msg|
send_msg(msg)
end

send_header
send_prompt

Channel << "#{@name} has joined."


end
end
module ChatClient
def post_init
@name = "anonymous"
@sid = Channel.subscribe do |msg|
send_msg(msg)
end

send_header
send_prompt

Channel << "#{@name} has joined."


end
end
module ChatClient
def post_init
@name = "anonymous"
@sid = Channel.subscribe do |msg|
send_msg(msg)
end

send_header
send_prompt

Channel << "#{@name} has joined."


end
end
module ChatClient
def unbind
Channel.unsubscribe(@sid)
Channel << "#{@name} has left."
end
end
module ChatClient
def receive_data data
@buf ||= ''
@buf << data

while line = @buf.slice!(/(.+)\r?\n/)


# ...
end
end
end
module ChatClient
def receive_data data
@buf ||= ''
@buf << data

while line = @buf.slice!(/(.+)\r?\n/)


# ...
end
end
end

...@buf?
rachel_thecat (flickr)
send_data(“hello”)
send_data(“world”)

network

receive_data(“he”)
receive_data(“llowo”)
receive_data(“rld”)
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.new
q.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 queue


SayQueue.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 queue


SayQueue.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” proc


SayQueue.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-request
require 'em-http'

http = EM::HttpRequest.new(
"http://stream.twitter.com/" +
"filter.json?track=#{tags.join(',')}"
).get(
:head => {
'authorization' => [user, pass]
}
)
# gem install yajl-ruby
require 'yajl'

parser = Yajl::Parser.new
parser.on_parse_complete = blk
http.stream do |data|
parser << data
end
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

rubinius
jruby
$ gem install eventmachine

rubinius
jruby
mri 1.8
$ gem install eventmachine

rubinius
jruby
mri 1.8
yarv 1.9
Code: http://github.com/eventmachine/eventmachine
Group: http://groups.google.com/group/eventmachine
RDoc: http://eventmachine.rubyforge.org
IRC: #eventmachine on irc.freenode.net
http://www.scribd.com/doc/28253878/EventMachine
QUESTIONS?
Aman Gupta
@tmm1
http://scribd.com/tmm1

Anda mungkin juga menyukai