ruby-changes:32539
From: glass <ko1@a...>
Date: Wed, 15 Jan 2014 20:37:29 +0900 (JST)
Subject: [ruby-changes:32539] glass:r44618 (trunk): * io.c (io_binwrite): use writev(2) to avoid double write if available.
glass 2014-01-15 20:37:23 +0900 (Wed, 15 Jan 2014) New Revision: 44618 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=44618 Log: * io.c (io_binwrite): use writev(2) to avoid double write if available. * configure.in: check writev(2) Modified files: trunk/ChangeLog trunk/configure.in trunk/io.c Index: configure.in =================================================================== --- configure.in (revision 44617) +++ configure.in (revision 44618) @@ -1122,6 +1122,7 @@ AC_CHECK_HEADERS( \ https://github.com/ruby/ruby/blob/trunk/configure.in#L1122 sys/socket.h \ process.h \ sys/prctl.h \ + sys/uio.h \ atomic.h \ malloc.h \ malloc_np.h \ @@ -1907,6 +1908,7 @@ AC_CHECK_FUNCS(malloc_usable_size) https://github.com/ruby/ruby/blob/trunk/configure.in#L1908 AC_CHECK_FUNCS(malloc_size) AC_CHECK_FUNCS(mblen) AC_CHECK_FUNCS(memalign) +AC_CHECK_FUNCS(writev) AC_CHECK_FUNCS(memrchr) AC_CHECK_FUNCS(mktime) AC_CHECK_FUNCS(pipe2) Index: ChangeLog =================================================================== --- ChangeLog (revision 44617) +++ ChangeLog (revision 44618) @@ -1,3 +1,9 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Wed Jan 15 20:30:31 2014 Masaki Matsushita <glass.saga@g...> + + * io.c (io_binwrite): use writev(2) to avoid double write if available. + + * configure.in: check writev(2) + Wed Jan 15 14:04:33 2014 Nobuyoshi Nakada <nobu@r...> * string.c (get_encoding): respect BOM on pseudo encodings. Index: io.c =================================================================== --- io.c (revision 44617) +++ io.c (revision 44618) @@ -86,6 +86,10 @@ https://github.com/ruby/ruby/blob/trunk/io.c#L86 #include <sys/syscall.h> #endif +#ifdef HAVE_SYS_UIO_H +#include <sys/uio.h> +#endif + #if defined(__BEOS__) || defined(__HAIKU__) # ifndef NOFILE # define NOFILE (OPEN_MAX) @@ -918,6 +922,14 @@ struct io_internal_write_struct { https://github.com/ruby/ruby/blob/trunk/io.c#L922 size_t capa; }; +#ifdef HAVE_WRITEV +struct io_internal_writev_struct { + int fd; + const struct iovec *iov; + int iovcnt; +}; +#endif + static VALUE internal_read_func(void *ptr) { @@ -939,6 +951,15 @@ internal_write_func2(void *ptr) https://github.com/ruby/ruby/blob/trunk/io.c#L951 return (void*)(intptr_t)write(iis->fd, iis->buf, iis->capa); } +#ifdef HAVE_WRITEV +static VALUE +internal_writev_func(void *ptr) +{ + struct io_internal_writev_struct *iis = ptr; + return writev(iis->fd, iis->iov, iis->iovcnt); +} +#endif + static ssize_t rb_read_internal(int fd, void *buf, size_t count) { @@ -973,6 +994,19 @@ rb_write_internal2(int fd, const void *b https://github.com/ruby/ruby/blob/trunk/io.c#L994 RUBY_UBF_IO, NULL); } +#ifdef HAVE_WRITEV +static ssize_t +rb_writev_internal(int fd, const struct iovec *iov, int iovcnt) +{ + struct io_internal_writev_struct iis; + iis.fd = fd; + iis.iov = iov; + iis.iovcnt = iovcnt; + + return (ssize_t)rb_thread_io_blocking_region(internal_writev_func, &iis, fd); +} +#endif + static long io_writable_length(rb_io_t *fptr, long l) { @@ -1201,13 +1235,75 @@ struct write_arg { https://github.com/ruby/ruby/blob/trunk/io.c#L1235 int nosync; }; +#ifdef HAVE_WRITEV static VALUE io_binwrite_string(VALUE arg) { struct binwrite_arg *p = (struct binwrite_arg *)arg; - long l = io_writable_length(p->fptr, p->length); - return rb_write_internal2(p->fptr->fd, p->ptr, l); + rb_io_t *fptr = p->fptr; + long r; + + if (fptr->wbuf.len) { + struct iovec iov[2]; + + iov[0].iov_base = fptr->wbuf.ptr+fptr->wbuf.off; + iov[0].iov_len = fptr->wbuf.len; + iov[1].iov_base = (char *)p->ptr; + iov[1].iov_len = p->length; + + r = rb_writev_internal(fptr->fd, iov, 2); + + if (fptr->wbuf.len <= r) { + r -= fptr->wbuf.len; + fptr->wbuf.off = 0; + fptr->wbuf.len = 0; + } + else { + fptr->wbuf.off += (int)r; + fptr->wbuf.len -= (int)r; + r = 0L; + } + } + else { + long l = io_writable_length(fptr, p->length); + r = rb_write_internal(fptr->fd, p->ptr, l); + } + + return r; +} +#else +static VALUE +io_binwrite_string(VALUE arg) +{ + struct binwrite_arg *p = (struct binwrite_arg *)arg; + rb_io_t *fptr = p->fptr; + long l, len; + + l = len = p->length; + + if (fptr->wbuf.len) { + if (fptr->wbuf.len+len <= fptr->wbuf.capa) { + if (fptr->wbuf.capa < fptr->wbuf.off+fptr->wbuf.len+len) { + MEMMOVE(fptr->wbuf.ptr, fptr->wbuf.ptr+fptr->wbuf.off, char, fptr->wbuf.len); + fptr->wbuf.off = 0; + } + MEMMOVE(fptr->wbuf.ptr+fptr->wbuf.off+fptr->wbuf.len, p->ptr, char, len); + fptr->wbuf.len += (int)len; + l = 0; + } + if (io_fflush(fptr) < 0) + return -2L; /* fail in fflush */ + if (l == 0) + return len; + } + + if (fptr->stdio_file != stderr && !rb_thread_fd_writable(fptr->fd)) + rb_io_check_closed(fptr); + + l = io_writable_length(p->fptr, p->length); + return rb_write_internal(p->fptr->fd, p->ptr, l); } +#endif static long io_binwrite(VALUE str, const char *ptr, long len, rb_io_t *fptr, int nosync) @@ -1230,27 +1326,6 @@ io_binwrite(VALUE str, const char *ptr, https://github.com/ruby/ruby/blob/trunk/io.c#L1326 (fptr->wbuf.ptr && fptr->wbuf.capa <= fptr->wbuf.len + len)) { struct binwrite_arg arg; - /* - * xxx: use writev to avoid double write if available - * writev may help avoid context switch between "a" and "\n" in - * STDERR.puts "a" [ruby-dev:25080] (rebroken since native threads - * introduced in 1.9) - */ - if (fptr->wbuf.len && fptr->wbuf.len+len <= fptr->wbuf.capa) { - if (fptr->wbuf.capa < fptr->wbuf.off+fptr->wbuf.len+len) { - MEMMOVE(fptr->wbuf.ptr, fptr->wbuf.ptr+fptr->wbuf.off, char, fptr->wbuf.len); - fptr->wbuf.off = 0; - } - MEMMOVE(fptr->wbuf.ptr+fptr->wbuf.off+fptr->wbuf.len, ptr+offset, char, len); - fptr->wbuf.len += (int)len; - n = 0; - } - if (io_fflush(fptr) < 0) - return -1L; - if (n == 0) - return len; - - rb_io_check_closed(fptr); arg.fptr = fptr; arg.str = str; retry: @@ -1260,8 +1335,7 @@ io_binwrite(VALUE str, const char *ptr, https://github.com/ruby/ruby/blob/trunk/io.c#L1335 r = rb_mutex_synchronize(fptr->write_lock, io_binwrite_string, (VALUE)&arg); } else { - long l = io_writable_length(fptr, n); - r = rb_write_internal(fptr->fd, ptr+offset, l); + r = io_binwrite_string((VALUE)&arg); } /* xxx: other threads may modify given string. */ if (r == n) return len; @@ -1269,7 +1343,9 @@ io_binwrite(VALUE str, const char *ptr, https://github.com/ruby/ruby/blob/trunk/io.c#L1343 offset += r; n -= r; errno = EAGAIN; - } + } + if (r == -2L) + return -1L; if (rb_io_wait_writable(fptr->fd)) { rb_io_check_closed(fptr); if (offset < len) @@ -9905,10 +9981,6 @@ simple_sendfile(int out_fd, int in_fd, o https://github.com/ruby/ruby/blob/trunk/io.c#L9981 */ # define USE_SENDFILE -# ifdef HAVE_SYS_UIO_H -# include <sys/uio.h> -# endif - static ssize_t simple_sendfile(int out_fd, int in_fd, off_t *offset, off_t count) { -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/