Beginner EM synchronization questions

140 views
Skip to first unread message

GT

unread,
May 22, 2012, 5:50:30 PM5/22/12
to EventMachine
Hi guys,

I have a couple of questions that I hope you could help me with.

Imagine my code is something like this:

values = { } # some data here

EM.run {
EM.add_periodic_timer(10) do

end

EM.defer do

end
}

I'm concerned about the thread safety of accessing/manipulating the
values hash. From what I've read, add_periodic_timer should not need
any synchronization ( as it runs in the main thread ), but operations
done in defer need synchronization ( as they execute in one of the
threads from the threadpool ). Is this right?

Thank you!

Iñaki Baz Castillo

unread,
May 23, 2012, 4:10:42 AM5/23/12
to eventm...@googlegroups.com
2012/5/22 GT <georgeo.d...@gmail.com>:
> but operations
> done in defer need synchronization ( as they execute in one of the
> threads from the threadpool ). Is this right?

Sure, the question is: why do you need threads? Ruby MRI can only use
a single native thread due to the GLI (GVL) so you won't get better
performance.

If you won't execute blocking code (this is, code that waits for I/O)
then use... EventMachine! :)
If you need to do blocking operations (this is, using Ruby libraries
that block for I/O but *release* the GIL/GVL) then use threads within
EM but, as you said, you must control those threads.

--
Iñaki Baz Castillo
<i...@aliax.net>

GT

unread,
May 23, 2012, 4:51:20 AM5/23/12
to EventMachine
I was thinking of deferring some database operations. I have a Rails
application and a Rack one that uses Faye inside EM.
Within the Faye application, I'm tracking disconnects, and I have to
periodically do some database managing ( stopping some sessions that
no longer have any connected users ).
Technically, that operation should be pretty fast, since my query
should return a pretty small set of objects, and modifying their state
just changes the value of a column in the database.
Do you think it should be like:

EM.add_periodic_timer(seconds) do
EM.defer do
end
end

or should I just eliminate the deferring?

Mark

unread,
May 23, 2012, 5:03:27 AM5/23/12
to eventm...@googlegroups.com
1. If your operations are fast (i.e. if your loop operates every T, operation should take less than T), then you don't have to worry about deferring
2. MRI/YARV don't have problems with synchronization because at any given point of time ONLY ONE ruby thread is operating simultaneously. Read more at igrigorik's blog: http://www.igvita.com/2008/11/13/concurrency-is-a-myth-in-ruby/
3. If you are still confused here's a case when you might actually need deferring:

EM.run do
  EM.add_periodic_timer(0.5) do
    EM.defer do
      begin
        do_some_operation_that_can_fail
      rescue OperationFailure
        sleep(1000) # try again in one second
        retry
      end
    end
  end
end

Kernel#sleep blocks the thread it is called in, thus stopping any EM reactor activity. Be warned, however, that EM.defer has a limited pool of threads. If all of them block, you will not be able to continue.

Iñaki Baz Castillo

unread,
May 23, 2012, 5:09:31 AM5/23/12
to eventm...@googlegroups.com
2012/5/23 GT <georgeo.d...@gmail.com>:
Take a look to https://github.com/igrigorik/em-synchrony (search for
mysql2 which is supported by Rails).

Iñaki Baz Castillo

unread,
May 23, 2012, 5:47:02 AM5/23/12
to eventm...@googlegroups.com
2012/5/23 Mark <mark...@gmail.com>:
> sleep(1000) # try again in one second

Then better sleep(1) ;)

GT

unread,
May 23, 2012, 5:51:15 AM5/23/12
to EventMachine
Makes sense. Quick question though: say you do manage to block the
reactor, would the blocked actions be queued up - so that they are
executed when it becomes free, or would they be lost?

Mark

unread,
May 23, 2012, 6:34:40 AM5/23/12
to eventm...@googlegroups.com
From my tests it looks like:
* periodic timer events (EM#add_periodic_timer) are dropped
* normal timer events (EM#add_timer) are queued

My guess is that network and other kinds of events are queued too.
Reply all
Reply to author
Forward
0 new messages