This is my test case, I found that the EM is not faster than the general TCP server
the EM serve开发者_Go百科r:
require 'rubygems'
require 'benchmark'
require 'eventmachine'
class Handler < EventMachine::Connection
def receive_data(data)
operation = proc do
# simulate a long running request
a = []
n = 5000
for i in 1..n
a << rand(n)
a.sort!
end
end
# Callback block to execute once the request is fulfilled
callback = proc do |res|
send_data "send_response\n"
end
puts data
EM.defer(operation, callback)
end
end
EventMachine::run {
EventMachine.epoll
EventMachine::start_server("0.0.0.0", 8080, Handler)
puts "Listening..."
}
and my benchmark test:
require 'rubygems'
require 'benchmark'
require 'socket'
Benchmark.bm do |x|
x.report("times:") do
for i in 1..20
TCPSocket.open "127.0.0.1", 8080 do |s|
s.send "#{i}th sending\n", 0
if line = s.gets
puts line
end
puts "#{i}th sending"
end
end
end
end
Simplicity compared to threads, not speed. Look here for more insights: EventMachine: Fast and Scalable Event-Driven I/O Framework
The citation that applies to your question:
A lot has been written about the fact that event-driven programs are not theoretically any faster than threaded ones, and that is true. But in practice, I think the event-driven model is easier to work with, if you want to get to extremely high scalability and performance while still ensuring maximum robustness. I write programs that have to run for months or years without crashing, leaking memory, or exhibiting any kind of lumpy performance, so in practice, event-driven programming works better. Now, here's the problem with event-driven programming: you have to write "backwards." A threaded model stores your program state (inefficiently) in local variables on a runtime stack. In EM you have to do that yourself, which is very unintuitive to programmers who are used to threads. This is why I'm interested in fibers, because it opens the possibility of writing what looks to the programmer like blocking I/O, but still is evented and uses no threads.
We just went through this exercise on our project yesterday. Conceptual hurdles abound.
Have a look at this demo rails app by Ilya Grigorik. He uses Apache Benchmark to hit the server concurrently as if you were getting traffic from multiple visitors to your site. This is where you get an advantage from eventmachine. Instead of having all the calls to the database line up behind each other, they are sent in asynchronously and the results are dramatic. If you install the demo you can see the difference by replacing the em_mysql2 adaptor(fast) with the mysql2 adaptor(slow) in database.yml
Likewise, if you hit eventmachine in a loop, you are constrained by the synchronous nature of the loop itself(slow).
One thing - you should call EM.epoll before entering the event loop with EM.run instead of inside it.
EventMachine.epoll
EventMachine::run {
EventMachine::start_server("0.0.0.0", 8080, Handler)
puts "Listening..."
}
精彩评论