threads and system calls

S

snacktime

I'm curious how ruby threads would do for a threaded network server.
Will reading/writing sockets in one thread block other threads? In
this application clients connect to the server via ssl and a simple
line protocol. They send requests to the server, and the server in
turn makes https connections to yet another server, gets the response,
and sends it's own response back to the client. Clients can send
multiple requests and stay connected as long as they want.

The servers that the application makes an https connection to speak
5-6 different protocols. Right now we have one application written in
perl that speaks 2 of them, and one in python's twisted that speaks
another. I want to consolidate everything into one application so I'm
evaluating my options. Perl is ok, no real complaints. Twisted is
amazingly fast for how few resources it consumes, but the code is
rather complicated and I'm not sure it's worth the extra performance.
I've used ruby for a while now but haven't used ruby threads and not
sure what kinds of issues I would run into with an application like
this. The application would need to be able to handle 20-30
concurrent clients each sending one request every 3-4 seconds. So
figure 40 or so ssl connections per second at the most plus the
connected clients, which will usually stay connected for long periods
of time.

Any advice or suggestions would be welcome.
 
F

Francis Cianfrocca

snacktime said:
I'm curious how ruby threads would do for a threaded network server.
Will reading/writing sockets in one thread block other threads? In
this application clients connect to the server via ssl and a simple
line protocol. They send requests to the server, and the server in
turn makes https connections to yet another server, gets the response,
and sends it's own response back to the client. Clients can send
multiple requests and stay connected as long as they want.

The servers that the application makes an https connection to speak
5-6 different protocols. Right now we have one application written in
perl that speaks 2 of them, and one in python's twisted that speaks
another. I want to consolidate everything into one application so I'm
evaluating my options. Perl is ok, no real complaints. Twisted is
amazingly fast for how few resources it consumes, but the code is
rather complicated and I'm not sure it's worth the extra performance.
I've used ruby for a while now but haven't used ruby threads and not
sure what kinds of issues I would run into with an application like
this. The application would need to be able to handle 20-30
concurrent clients each sending one request every 3-4 seconds. So
figure 40 or so ssl connections per second at the most plus the
connected clients, which will usually stay connected for long periods
of time.

Any advice or suggestions would be welcome.

Look at EventMachine (Rubyforge) for a ruby implementation of something
much like Twisted at least as fast and relatively efficient too. EM
supports SSL, can easily handle multiple protocols and isn't very hard
to use. The latest (unpublished) versions support thread-pools and
locally-blocking functions (like Twisted's Deferreds) if you need them.
We don't have a large library of standard protocols like Twisted yet,
but they are coming.
 
S

snacktime

Look at EventMachine (Rubyforge) for a ruby implementation of something
much like Twisted at least as fast and relatively efficient too. EM
supports SSL, can easily handle multiple protocols and isn't very hard
to use. The latest (unpublished) versions support thread-pools and
locally-blocking functions (like Twisted's Deferreds) if you need them.
We don't have a large library of standard protocols like Twisted yet,
but they are coming.

I had actually been keeping an eye on EventMachine, just hadn't taken
the time to play around with it yet. Do you mean that you can do
something similar to twisted's defertothread? ie, calling local
blocking functions and have them run in the thread pool and be able to
specify a callback of some type?
 
S

snacktime

Ok I grabbed the source from the svn repo and am looking through it.
Looks like there are enough samples and code there to get an idea of
how it all works.
 
F

Francis Cianfrocca

snacktime said:
Ok I grabbed the source from the svn repo and am looking through it.
Looks like there are enough samples and code there to get an idea of
how it all works.

Sounds like you figured it out. You get the defertothread-like behavior
with EventMachine#defer and there is a code sample in the Rdoc. Very
simple.

The Deferrable pattern is a separate feature that doesn't require thread
pools to work. Deferrable is illustrated with the TcpConnectTester in
the protocols directory, and it's also very simple although there isn't
much documentation of the pattern yet.

The idea here is identical to Twisted's Deferred object. You start with
an ordinary class of your own, like a network-protocol handler, that is
written to receive normal EventMachine events. Include
EventMachine::Deferrable in your class and then instantiate your objects
as you normally would. The Deferrable module adds several methods to
your class: #callback, #errback, and #set_deferred_status(status,
*args). As long as your object exists in memory, your program can add
code blocks to it via one or more calls to callback and errback, and set
the object's "status" (notionally, the outcome of the deferred operation
that it performs) via #set_deferred_status. If the status is :succeeded,
then all of the code blocks added via #callback are automatically called
in order with the arguments passed to #set_deferred_status. If status is
:failed, the #errback chain is called. As with Twisted, you can call
#callback and #errback even after the operation status is known.

But in your OP, you didn't say anything about needing Deferrables or
locally-blocking operations. Sounds like you're trying to do a
plain-vanilla multi-platform network server. If you need the newer
stuff, let me know and I'll publish a new release and add some more
docs.

The big problem that Windows users have with EM is that it's a compiled
extension. Let me know if you have trouble with it. I just made a win32
binary gem the other day for EM version 0.7.0. I'd like to release a
pure-Ruby version of EM someday soon, although there are currently two
problems with it: it's about half as fast as the extension (although
that is probably plenty fast enough for most applications), and it
requires a recent snap of Ruby 1.8.5 to get needed improvements to
nonblocking I/O.
 
S

snacktime

Am I correct that version_0 in the repository is the current branch
you are releasing from? I was just playing around with creating a
simple line handling protocol using some of the code you had in
another directory.

Also, any suggestions on how to implement a pool of database
connections that can be reused?
 
F

Francis Cianfrocca

Am I correct that version_0 in the repository is the current branch
you are releasing from? I was just playing around with creating a
simple line handling protocol using some of the code you had in
another directory.

Also, any suggestions on how to implement a pool of database
connections that can be reused?

Version_0 is the current release branch. The other ones are
experimental and pure-ruby branches. The obvious way to do a
connection pool would be with Ruby's thread-safe Queue object. You
could pull a connection off when you needed one and do the work with
EventMachine#defer. If this doesn't make any sense, please let me
know. It's probably worth having a connection pool implemented in a
standard way in the library itself.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top