ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-Fork-RPC/RPC.pm
(Generate patch)

Comparing AnyEvent-Fork-RPC/RPC.pm (file contents):
Revision 1.11 by root, Thu Apr 18 07:59:46 2013 UTC vs.
Revision 1.13 by root, Thu Apr 18 11:11:26 2013 UTC

489 } 489 }
490 } elsif (defined $len) { 490 } elsif (defined $len) {
491 undef $rw; undef $ww; # it ends here 491 undef $rw; undef $ww; # it ends here
492 492
493 if (@rcb || %rcb) { 493 if (@rcb || %rcb) {
494 use Data::Dump;ddx[\@rcb,\%rcb];#d#
495 $on_error->("unexpected eof"); 494 $on_error->("unexpected eof");
496 } else { 495 } else {
497 $on_destroy->(); 496 $on_destroy->();
498 } 497 }
499 } elsif ($! != Errno::EAGAIN && $! != Errno::EWOULDBLOCK) { 498 } elsif ($! != Errno::EAGAIN && $! != Errno::EWOULDBLOCK) {
579See the examples section earlier in this document for some actual 578See the examples section earlier in this document for some actual
580examples. 579examples.
581 580
582=back 581=back
583 582
583=head1 ADVANCED TOPICS
584
585=head2 Choosing a backend
586
587So how do you decide which backend to use? Well, that's your problem to
588solve, but here are some thoughts on the matter:
589
590=over 4
591
592=item Synchronous
593
594The synchronous backend does not rely on any external modules (well,
595except L<common::sense>, which works around a bug in how perl's warning
596system works). This keeps the process very small, for example, on my
597system, an empty perl interpreter uses 1492kB RSS, which becomes 2020kB
598after C<use warnings; use strict> (for people who grew up with C64s around
599them this is probably shocking every single time they see it). The worker
600process in the first example in this document uses 1792kB.
601
602Since the calls are done synchronously, slow jobs will keep newer jobs
603from executing.
604
605The synchronous backend also has no overhead due to running an event loop
606- reading requests is therefore very efficient, while writing responses is
607less so, as every response results in a write syscall.
608
609If the parent process is busy and a bit slow reading responses, the child
610waits instead of processing further requests. This also limits the amount
611of memory needed for buffering, as never more than one response has to be
612buffered.
613
614The API in the child is simple - you just have to define a function that
615does something and returns something.
616
617It's hard to use modules or code that relies on an event loop, as the
618child cannot execute anything while it waits for more input.
619
620=item Asynchronous
621
622The asynchronous backend relies on L<AnyEvent>, which tries to be small,
623but still comes at a price: On my system, the worker from example 1a uses
6243420kB RSS (for L<AnyEvent>, which loads L<EV>, which needs L<XSLoader>
625which in turn loads a lot of other modules such as L<warnings>, L<strict>,
626L<vars>, L<Exporter>...).
627
628It batches requests and responses reasonably efficiently, doing only as
629few reads and writes as needed, but needs to poll for events via the event
630loop.
631
632Responses are queued when the parent process is busy. This means the child
633can continue to execute any queued requests. It also means that a child
634might queue a lot of responses in memory when it generates them and the
635parent process is slow accepting them.
636
637The API is not a straightforward RPC pattern - you have to call a
638"done" callback to pass return values and signal completion. Also, more
639importantly, the API starts jobs as fast as possible - when 1000 jobs
640are queued and the jobs are slow, they will all run concurrently. The
641child must implement some queueing/limiting mechanism if this causes
642problems. Alternatively, the parent could limit the amount of rpc calls
643that are outstanding.
644
645Using event-based modules such as L<IO::AIO>, L<Gtk2>, L<Tk> and so on is
646easy.
647
648=back
649
650=head2 Passing file descriptors
651
652Unlike L<AnyEvent::Fork>, this module has no in-built file handle or file
653descriptor passing abilities.
654
655The reason is that passing file descriptors is extraordinary tricky
656business, and conflicts with efficient batching of messages.
657
658There still is a method you can use: Create a
659C<AnyEvent::Util::portable_socketpair> and C<send_fh> one half of it to
660the process before you pass control to C<AnyEvent::Fork::RPC::run>.
661
662Whenever you want to pass a file descriptor, send an rpc request to the
663child process (so it expects the descriptor), then send it over the other
664half of the socketpair. The child should fetch the descriptor from the
665half it has passed earlier.
666
667Here is some (untested) pseudocode to that effect:
668
669 use AnyEvent::Util;
670 use AnyEvent::Fork::RPC;
671 use IO::FDPass;
672
673 my ($s1, $s2) = AnyEvent::Util::portable_socketpair;
674
675 my $rpc = AnyEvent::Fork
676 ->new
677 ->send_fh ($s2)
678 ->require ("MyWorker")
679 ->AnyEvent::Fork::RPC::run ("MyWorker::run"
680 init => "MyWorker::init",
681 );
682
683 undef $s2; # no need to keep it around
684
685 # pass an fd
686 $rpc->("i'll send some fd now, please expect it!", my $cv = AE::cv);
687
688 IO::FDPass fileno $s1, fileno $handle_to_pass;
689
690 $cv->recv;
691
692The MyWorker module could look like this:
693
694 package MyWorker;
695
696 use IO::FDPass;
697
698 my $s2;
699
700 sub init {
701 $s2 = $_[0];
702 }
703
704 sub run {
705 if ($_[0] eq "i'll send some fd now, please expect it!") {
706 my $fd = IO::FDPass::recv fileno $s2;
707 ...
708 }
709 }
710
711Of course, this might be blocking if you pass a lot of file descriptors,
712so you might want to look into L<AnyEvent::FDpasser> which can handle the
713gory details.
714
584=head1 SEE ALSO 715=head1 SEE ALSO
585 716
586L<AnyEvent::Fork> (to create the processes in the first place), 717L<AnyEvent::Fork> (to create the processes in the first place),
587L<AnyEvent::Fork::Pool> (to manage whole pools of processes). 718L<AnyEvent::Fork::Pool> (to manage whole pools of processes).
588 719

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines