Mark Van De Vyver
2007-May-24 13:04 UTC
[Eventmachine-talk] Multiple EM connections on separate threads
Hi EM Gurus, I''m hoping someone can shed some light on the following... I''m using a 3rd party (legacy) server that can accept up to 8 simultaneous connections on one port. I''ve been able to make multiple connections to this server from within one call to EventMachine::run {...}. Specificaly, I can access each connection separately using: em_thread = Thread.new do EventMachine::run { t = Thread.current [:c1, :c2, :c3].each do |i| t[i] = EventMachine::connect host, port, IB::MyEMConnection puts "Established connection #{i} to address #{host}, port #{port}..." end # conn_list.each do |i| } # EventMachine::run { This means that all connections are running in one thread. What I would like to do, is make each connection run in a separate thread. I have tried unsuccessfully to do this two ways. First, by starting a new thread inside the EM::run{..}. Even with limited understanding of threads in ruby this didn''t make sense, but I tried it anyway - no joy. The first part of the EM error is below: /usr/lib/ruby/gems/1.8/gems/eventmachine-0.7.0/lib/eventmachine.rb:793:in `event_callback'': EventMachine::ConnectionNotBound (EventMachine::ConnectionNotBound) from /usr/lib/ruby/gems/1.8/gems/eventmachine-0.7.0/lib/eventmachine.rb:201:in `run_machine'' from /usr/lib/ruby/gems/1.8/gems/eventmachine-0.7.0/lib/eventmachine.rb:201:in `run'' Second, I tried to create a separate instances of the EM::run{..}, each in its own thread. This I _was_ pinning my hopes on.... conn_list = [] 8.times do |number| conn_list << Thread.new do EventMachine::run { t = Thread.current t[:conn] = EventMachine::connect host, port, IB::MyEMConnection } # EventMachine::run { end # conn_list << Thread.new(number) do |i| puts "Established connection #{number} to address #{host}, port #{port}...\n" end # 8.times do |number| This too didn''t work. The stdout error I see is: terminate called after throwing an instance of ''std::runtime_error'' what(): already initialized Aborted Is it sane/legitimate/possible to start EM in the way I am attempting? If so, can anyone suggest what I''ve done incorrectly? Regards Mark
Francis Cianfrocca
2007-May-24 13:10 UTC
[Eventmachine-talk] Multiple EM connections on separate threads
On 5/24/07, Mark Van De Vyver <mvyver at gmail.com> wrote:> > Hi EM Gurus, > I''m hoping someone can shed some light on the following... > > I''m using a 3rd party (legacy) server that can accept up to 8 > simultaneous connections on one port. > I''ve been able to make multiple connections to this server from within > one call to EventMachine::run {...}.Exactly why do you need multiple threads? Thinking in terms of events, you''d generally look for a way for these connections to all run on one thread. You mention a legacy server. What network protocol is it running? A standard one or a homebrew? -------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/eventmachine-talk/attachments/20070524/129d2cf2/attachment.html
Mark Van De Vyver
2007-May-24 16:21 UTC
[Eventmachine-talk] Multiple EM connections on separate threads
Hi Francis, On 5/25/07, Francis Cianfrocca <garbagecat10 at gmail.com> wrote:> On 5/24/07, Mark Van De Vyver <mvyver at gmail.com> wrote: > > There are several ''types/classes'' of messages I can receive from this > > server. Some can be processed very simply, and take next to no time, > > others can take more time to ''digest''. So I hoped to minimize the > > backlog that builds up. The messages should be processed in order, and > > can affect what is done with a following message, so I think this > > prevents me placing the ''digestion'' part of the process in a separate > > thread. Also, it seemed to me that ''threading'' the calculation part > > of my code was going to be more tricky, and the cleanest solution was > > to create separate threads for each of the 8 EM connections. > > > Ok, well, on a very simple analysis, you should avoid threads here because > they don''t add any value. Especially on Ruby, you''ll net out with so much > extra overhead that you''ll probably end up slower than without them, > probably by quite a lot. Keep it simple until you''re sure you need a more > complex approach.OK. Consider them on the ''to-be-avoided'' list :)> However, there is some subtlety to this! You''re concerned about backlogging > the system while processing messages that take a long time to process. I can > see trouble ahead if the processing requires database calls. Does it? If so, > then look at EM''s built-in thread pool (EventMachine#defer). If there''s no > external latency, then I stick to my story and advise you to avoid threads.At the moment there are no db calls. This was something I was going to add later, and will now try and separate this from the code running under the EM''s scope. Thanks for the heads-up.> Having said all that, I''ll reiterate the basic axiom: network and I/O > processing almost always dominate the runtime profile. CPU time is usually > negligible. If your message processing is all intramachine and not dependent > on resources you don''t control, then you should avoid optimizing it. It will > usually come out in the wash. >OK> Database calls are always the exception, because until someone convinces me > that we need evented versions of the standard RDBMS libraries, they will > always be blocking calls that introduce uncontrollable latency. >I think I can set things up to avoid db calls while processing a message using an EM.> Come back and ask some more questions if any of this makes no sense. > > > > > The network protocol is TCP. The server app and the ''client code'' are > > both on the local machine, all connections use the IP address > > 127.0.0.1. > > > I meant what is the application-level protocol being used? Is it HTTP? XMPP? > Or some homebrew? >No it is ''homebrewed'', and poorly documented :( Thanks again for the helpful advice. Regards Mark>
Francis Cianfrocca
2007-May-25 04:37 UTC
[Eventmachine-talk] Multiple EM connections on separate threads
Mark, I wanted to be sure I didn''t scare you away from making DB calls inside an EM message handler. The way to do them is with EventMachine#defer, which is reasonably well-documented. You might do something like: def receive_data data ... process data ... call_db = proc do ... make db calls here ... @the_response = data_from_the_db end send_response = proc do send_data @the_response end EventMachine.defer( call_db, send_response ) end As you see, you pass two procs to EventMachine#defer. The first one is executed on a separate Ruby thread, managed by EM. You can do blocking calls here and the main reactor loop will still run at full speed. The (optional) second proc is executed on EM''s main reactor thread when the first proc completes. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/eventmachine-talk/attachments/20070525/4e1afcaf/attachment-0001.html
Mark Van De Vyver
2007-May-25 05:56 UTC
[Eventmachine-talk] Multiple EM connections on separate threads
Hi Francis, On 5/25/07, Francis Cianfrocca <garbagecat10 at gmail.com> wrote:> Mark, I wanted to be sure I didn''t scare you away from making DB calls > inside an EM message handler. The way to do them is with EventMachine#defer, > which is reasonably well-documented. You might do something like: >Thanks for the additional info. That does help - alot. You''ve clearly experienced and thought all this through. The code fragment looks like a very flexible and neat solution. Much appreciated Regards Mark> def receive_data data > ... process data ... > > call_db = proc do > ... make db calls here ... > @the_response = data_from_the_db > end > > send_response = proc do > send_data @the_response > end > > EventMachine.defer( call_db, send_response ) > > end > > As you see, you pass two procs to EventMachine#defer. The first one is > executed on a separate Ruby thread, managed by EM. You can do blocking calls > here and the main reactor loop will still run at full speed. The (optional) > second proc is executed on EM''s main reactor thread when the first proc > completes. >