NAME IO::Vectored - Read from or write to multiple buffers at once WRITE SYNOPSIS use IO::Vectored; syswritev($file_handle, "hello", "world") || die "syswritev: $!"; READ SYNOPSIS use IO::Vectored; my $buf1 = " " x 5; my $buf2 = " " x 5; sysreadv($file_handle, $buf1, $buf2) || die "sysreadv: $!"; ## if input is "abcdefg" then: ## $buf1 eq "abcde" ## $buf2 eq "fg " DESCRIPTION Vectored-IO is sometimes called "scatter/gather IO". The idea is that instead of doing multiple read(2) or write(2) system calls for each string you wish to read/write, your userspace program creates a vector of pointers to the various strings and does a single system call. Although some people consider these interfaces contrary to the simple design principles of unix, they provide certain advantages which are described below. This module is an interface to your system's and vectored-IO system calls specified by POSIX.1. It exports the functions "syswritev" and "sysreadv" which are almost the same as the syswrite and sysread perl functions except for some minor differences described below. ADVANTAGES The first advantage of vectored-IO is that it reduces the number of system calls required. This will provide an atomicity guarantee for the writing of the data and also eliminate a constant performance overhead. Another potential advantage of vectored-IO is that doing multiple system calls can sometimes result in excessive network packets being sent. The classic example of this is a web-server handling a static file. If the server write(2)s the HTTP headers and then write(2)s the file data, the kernel might send the headers and file in separate network packets. A single packet would be better for latency and bandwidth. is a solution to this issue but it is linux-specific and can require more system calls. Of course an alternative to vectored-IO is to copy the buffers together into a contiguous buffer before calling write(2). The performance trade-off is that a potentially large buffer needs to be allocated and then all the smaller buffers copied into it. Also, if your buffers are backed by memory-mapped files (created with say File::Map) then this approach results in an unnecessary copy of the data to userspace. If you use vectored-IO then files can be copied directly from the file-system cache into the socket's . The non-standard sendfile(2) system call can theoretically do one fewer copy but it requires a system call for each file sent, unlike vectored-IO. Note that as with anything the performance benefits of vectored-IO will vary from application to application and you shouldn't retro-fit it onto an application unless benchmarking has shown measurable benefits. However, vectored-IO can sometimes be more programmer convenient than regular IO and may be worth using for that reason alone. RETURN VALUES AND ERROR CONDITIONS As mentioned above, this module's interface tries to match "syswrite" and "sysread" so the same caveats that apply to those functions apply to the vectored interfaces. In particular, you should not mix these calls with userspace-buffered interfaces such as print or seek. Mixing the vectored interfaces with "syswrite" and "sysread" is fine though. "syswritev" returns the number of bytes written (usually the sum of the lengths of all arguments). If it returns less, either there was an error indicated in $! or you are using non-blocking IO in which case it is up to you to adjust it so that the next "syswritev" points to the rest of the data. "sysreadv" returns the number of bytes read up to the sum of the lengths of all arguments. Note that unlike "sysread", "sysreadv" will not truncate any buffers (see the "READ SYNOPSIS" above and the TODO below). Both of these functions can also return "undef" if the underlying readv(2) or writev(2) system calls fail for any reason other than "EINTR". In this case, $! will be set with the error. Like "sysread"/"syswrite", the vectored versions also croak for various reasons (see the "t/exceptions.t" test for a full list). Some examples are: passing in too many arguments (greater than the "IO::Vectored::IOV_MAX" constant), trying to use a closed file-handle, and trying to write to a read-only/constant string. TODO To the extent possible, make it do the right thing for file-handles with non-raw encodings and unicode strings. Any test-cases are appreciated. Investigate if there is a performance benefit in eliminating the perl wrapper subs and re-implementing their logic in XS. Think about truncating strings like "sysread" does. Please don't depend on the non-truncation behaviour of "sysreadv" until version 1.000: You have been warned. :) Think about whether this module should support vectors larger than "IOV_MAX" by calling "writev"/"readv" multiple times. This should probably be opt-in because it breaks atomicity guarantees. Support windows with "ReadFileScatter", "WriteFileGather", "WSASend", and "WSARecv". SEE ALSO Useful modules to combine with vectored-IO: File::Map / Sys::Mmap String::Slice / overload::substr "sendfile()" is less general than and not really compatible with vectored-IO, but here are some perl interfaces: Sys::Sendfile / Sys::Syscall / Sys::Sendfile::FreeBSD AUTHOR Doug Hoyte, "" COPYRIGHT & LICENSE Copyright 2013 Doug Hoyte. This module is licensed under the same terms as perl itself.