Kacheong Poon wrote:
> The following loop is quite common in a lot of socket
> apps (the example is for reading data) .
> 
>       select(<on a bunch of sockets>);
>       foreach socket with read events {
>               recv(<data>);
>               process(<data>);
>       }
> 
> In Solaris 10 with event port, the select() may be
> replaced by say, port_getn().  But the result is
> the same, the app knows that there are a bunch of
> sockets ready to be handled.  Currently, each socket
> needs to be handled independently.  Stephen Uhler
> from Sun Lab suggested that we can have a new socket
> call which can handle a bunch of sockets at the same
> time.  Doing this can save a lot of socket calls.
> and context switches.
> 
> Using recvfrom() as an example,
> 
> struct rd_list {
>          int             sd;
>          void            *buf;
>          size_t          buf_len;
>          struct sockaddr *from;
>          socklen_t       *from_len;
>          int             flags;
>          int             *num_recv;
> };
> 
> int recvfrom_list(struct rd_list[], size_t list_size);
> 
> Basically, struct rd_list contains all the parameters
> of the recvfrom() call.  And the recvfrom_list() takes
> an array of struct rd_list.  In return, it fills in each
> element with the appropriate data as if a non-blocking
> recvfrom() is called on each socket.  We can also have
> recv_list() and recvmsg_list().
> 
> The idea can also be applied to the sending side.  For
> example, we can have sendto_list().
> 
> What do people think of this proposal?  Please comment.
> 
> 

The savings here are basically the reduction of system call
overhead.... we still have per-filedescriptor costs on each select.
Also, such event loops are notoriously hard to thread; the select loop
requires a dispatcher thread.  Why not do the following:

Define a new asynchronous call similar to lio_listio that permits
the collection of struct sockaddr & socklen_t info.  This would
then generate async io completion events, which could be retrieved
via an event port once the IO had completed.

The advantage of such a design is that by having multiple async
read requests pending in the kernel on each fd, per-descriptor
latencies are reduced significantly since we don't have a
delay due to returning from poll/select, scanning the descriptor
list, and calling back into the kernel w/ recfrom_list, processing
the results and then calling select/poll again.  Also more threads
can be brought to bear, a useful technique on CMT processors.
Even threading-averse programmers can still benefit from
multiple kernel threads copying out the data into the
pre-posted receive buffers, and process the requests as they
complete in a single thread.  Lastly, read side I/O buffer pre-posting
also enables utilization of more sophisticated NICs and such 
technologies as Intel's IOAT.

- Bart


-- 
Bart Smaalders                  Solaris Kernel Performance
[EMAIL PROTECTED]               http://blogs.sun.com/barts
_______________________________________________
networking-discuss mailing list
networking-discuss@opensolaris.org

Reply via email to