Brian Candler
10/4/2004 8:39:00 AM
On Mon, Oct 04, 2004 at 07:42:14AM +0900, David G. Andersen wrote:
> Ruby's threads seem "generally pretty good" about not blocking
> on IO calls _if_ you do them right. An example from a program
> I was working on:
>
> mybuf.sbuf += s.sysread(65536)
> vs
> mybuf.sbuf += s.sysread(4096)
>
> The former caused (all of) Ruby to block. The latter
> was handled properly. I _assume_, but didn't verify,
> that this is because Ruby was doing something like
>
> select()
> read(foo)
>
> internally
Essentially that's right. Was there any reason to use 'sysread' rather than
'read'? I think that
mybuf.sbuf += s.read(65536)
probably would have worked as you'd expected.
> In _general_, you shouldn't have to use nonblocking IO,
> but there are likely operations that Ruby can't make internally
> nonblocking. DNS lookups are often a pain to perform
> asynchronously unless you explicitly use an async
> DNS library, for instance. File operations over
> NFS can block and are next to impossible to
> deal with without either multiple processes or
> kernel-level multithreading (particularly metadata
> operations like lookup and open).
All good points. I'd just add that things like external database libraries
(e.g. mysql) tend to block too. I've seen some which don't; the Oracle OCI8
binding for ruby has the ability to be put in a 'nonblocking' mode, but what
it actually does is poll for a result after 1ms, 2ms, 4ms, 8ms...etc !
For such applications, separate processes are often essential. For web
applications I've had a lot of success with fcgi, where a pool of persistent
processes is set up by Apache under mod_fastcgi, and each one only handles a
single request at a time. This means you don't have to worry about thread
safety as well as blocking.
Regards,
Brian.