EventMachine的优点是什么?

时间:2011-04-29 09:06:47

标签: ruby tcp eventmachine

这是我的测试用例,我发现EM并不比普通的TCP服务器快

EM服务器:

    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..."
    }

和我的基准测试:

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

3 个答案:

答案 0 :(得分:3)

与线程相比简单,而不是速度。在此处查看更多见解:EventMachine: Fast and Scalable Event-Driven I/O Framework

适用于您的问题的引文:

  

关于事件驱动程序在理论上并不比线程程序更快的事实已经写了很多,这是事实。但实际上,如果您希望获得极高的可扩展性和性能,同时仍然确保最大的稳健性,我认为事件驱动的模型更容易使用。我编写的程序必须运行数月或数年而不会崩溃,泄漏内存或表现出任何类型的块状性能,所以在实践中,事件驱动编程效果更好。现在,这是事件驱动编程的问题:你必须写“向后”。线程模型将程序状态(低效率)存储在运行时堆栈上的局部变量中。在EM中你必须自己做,这对于习惯于线程的程序员来说非常不直观。这就是我对光纤感兴趣的原因,因为它开启了编写看起来像程序员看起来像阻塞I / O的可能性,但仍然是偶数并且不使用线程。

答案 1 :(得分:1)

我们昨天刚刚对我们的项目进行了这项练习。概念障碍比比皆是。

请看Ilya Grigorik的this demo rails app。他使用Apache Benchmark同时访问服务器,就像从多个访问者那里获得流量一样。这是您从eventmachine获得优势的地方。它们不是将对数据库的所有调用排在一起,而是异步发送,结果非常引人注目。如果您安装了演示,您可以通过在database.yml中用mysql2适配器(慢速)替换em_mysql2适配器(快速)来看到差异

同样,如果你在循环中点击eventmachine,你会受到循环本身的同步特性的限制(慢)。

答案 2 :(得分:0)

有一件事 - 在使用EM.run而不是在其中进入事件循环之前,您应该调用EM.epoll。

EventMachine.epoll
EventMachine::run {
  EventMachine::start_server("0.0.0.0", 8080, Handler)
  puts "Listening..."
}