[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]