mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* io.c (io_binwrite): use writev(2) to avoid double write if available.
* configure.in: check writev(2) git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@44618 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
82ab2d6d6a
commit
bddde8eee3
3 changed files with 110 additions and 30 deletions
|
@ -1,3 +1,9 @@
|
||||||
|
Wed Jan 15 20:30:31 2014 Masaki Matsushita <glass.saga@gmail.com>
|
||||||
|
|
||||||
|
* 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@ruby-lang.org>
|
Wed Jan 15 14:04:33 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
* string.c (get_encoding): respect BOM on pseudo encodings.
|
* string.c (get_encoding): respect BOM on pseudo encodings.
|
||||||
|
|
|
@ -1122,6 +1122,7 @@ AC_CHECK_HEADERS( \
|
||||||
sys/socket.h \
|
sys/socket.h \
|
||||||
process.h \
|
process.h \
|
||||||
sys/prctl.h \
|
sys/prctl.h \
|
||||||
|
sys/uio.h \
|
||||||
atomic.h \
|
atomic.h \
|
||||||
malloc.h \
|
malloc.h \
|
||||||
malloc_np.h \
|
malloc_np.h \
|
||||||
|
@ -1907,6 +1908,7 @@ AC_CHECK_FUNCS(malloc_usable_size)
|
||||||
AC_CHECK_FUNCS(malloc_size)
|
AC_CHECK_FUNCS(malloc_size)
|
||||||
AC_CHECK_FUNCS(mblen)
|
AC_CHECK_FUNCS(mblen)
|
||||||
AC_CHECK_FUNCS(memalign)
|
AC_CHECK_FUNCS(memalign)
|
||||||
|
AC_CHECK_FUNCS(writev)
|
||||||
AC_CHECK_FUNCS(memrchr)
|
AC_CHECK_FUNCS(memrchr)
|
||||||
AC_CHECK_FUNCS(mktime)
|
AC_CHECK_FUNCS(mktime)
|
||||||
AC_CHECK_FUNCS(pipe2)
|
AC_CHECK_FUNCS(pipe2)
|
||||||
|
|
132
io.c
132
io.c
|
@ -86,6 +86,10 @@
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_UIO_H
|
||||||
|
#include <sys/uio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(__BEOS__) || defined(__HAIKU__)
|
#if defined(__BEOS__) || defined(__HAIKU__)
|
||||||
# ifndef NOFILE
|
# ifndef NOFILE
|
||||||
# define NOFILE (OPEN_MAX)
|
# define NOFILE (OPEN_MAX)
|
||||||
|
@ -918,6 +922,14 @@ struct io_internal_write_struct {
|
||||||
size_t capa;
|
size_t capa;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef HAVE_WRITEV
|
||||||
|
struct io_internal_writev_struct {
|
||||||
|
int fd;
|
||||||
|
const struct iovec *iov;
|
||||||
|
int iovcnt;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
internal_read_func(void *ptr)
|
internal_read_func(void *ptr)
|
||||||
{
|
{
|
||||||
|
@ -939,6 +951,15 @@ internal_write_func2(void *ptr)
|
||||||
return (void*)(intptr_t)write(iis->fd, iis->buf, iis->capa);
|
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
|
static ssize_t
|
||||||
rb_read_internal(int fd, void *buf, size_t count)
|
rb_read_internal(int fd, void *buf, size_t count)
|
||||||
{
|
{
|
||||||
|
@ -973,6 +994,19 @@ rb_write_internal2(int fd, const void *buf, size_t count)
|
||||||
RUBY_UBF_IO, NULL);
|
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
|
static long
|
||||||
io_writable_length(rb_io_t *fptr, long l)
|
io_writable_length(rb_io_t *fptr, long l)
|
||||||
{
|
{
|
||||||
|
@ -1201,13 +1235,75 @@ struct write_arg {
|
||||||
int nosync;
|
int nosync;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef HAVE_WRITEV
|
||||||
static VALUE
|
static VALUE
|
||||||
io_binwrite_string(VALUE arg)
|
io_binwrite_string(VALUE arg)
|
||||||
{
|
{
|
||||||
struct binwrite_arg *p = (struct binwrite_arg *)arg;
|
struct binwrite_arg *p = (struct binwrite_arg *)arg;
|
||||||
long l = io_writable_length(p->fptr, p->length);
|
rb_io_t *fptr = p->fptr;
|
||||||
return rb_write_internal2(p->fptr->fd, p->ptr, l);
|
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
|
static long
|
||||||
io_binwrite(VALUE str, const char *ptr, long len, rb_io_t *fptr, int nosync)
|
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, long len, rb_io_t *fptr, int nosync)
|
||||||
(fptr->wbuf.ptr && fptr->wbuf.capa <= fptr->wbuf.len + len)) {
|
(fptr->wbuf.ptr && fptr->wbuf.capa <= fptr->wbuf.len + len)) {
|
||||||
struct binwrite_arg arg;
|
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.fptr = fptr;
|
||||||
arg.str = str;
|
arg.str = str;
|
||||||
retry:
|
retry:
|
||||||
|
@ -1260,8 +1335,7 @@ io_binwrite(VALUE str, const char *ptr, long len, rb_io_t *fptr, int nosync)
|
||||||
r = rb_mutex_synchronize(fptr->write_lock, io_binwrite_string, (VALUE)&arg);
|
r = rb_mutex_synchronize(fptr->write_lock, io_binwrite_string, (VALUE)&arg);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
long l = io_writable_length(fptr, n);
|
r = io_binwrite_string((VALUE)&arg);
|
||||||
r = rb_write_internal(fptr->fd, ptr+offset, l);
|
|
||||||
}
|
}
|
||||||
/* xxx: other threads may modify given string. */
|
/* xxx: other threads may modify given string. */
|
||||||
if (r == n) return len;
|
if (r == n) return len;
|
||||||
|
@ -1269,7 +1343,9 @@ io_binwrite(VALUE str, const char *ptr, long len, rb_io_t *fptr, int nosync)
|
||||||
offset += r;
|
offset += r;
|
||||||
n -= r;
|
n -= r;
|
||||||
errno = EAGAIN;
|
errno = EAGAIN;
|
||||||
}
|
}
|
||||||
|
if (r == -2L)
|
||||||
|
return -1L;
|
||||||
if (rb_io_wait_writable(fptr->fd)) {
|
if (rb_io_wait_writable(fptr->fd)) {
|
||||||
rb_io_check_closed(fptr);
|
rb_io_check_closed(fptr);
|
||||||
if (offset < len)
|
if (offset < len)
|
||||||
|
@ -9905,10 +9981,6 @@ simple_sendfile(int out_fd, int in_fd, off_t *offset, off_t count)
|
||||||
*/
|
*/
|
||||||
# define USE_SENDFILE
|
# define USE_SENDFILE
|
||||||
|
|
||||||
# ifdef HAVE_SYS_UIO_H
|
|
||||||
# include <sys/uio.h>
|
|
||||||
# endif
|
|
||||||
|
|
||||||
static ssize_t
|
static ssize_t
|
||||||
simple_sendfile(int out_fd, int in_fd, off_t *offset, off_t count)
|
simple_sendfile(int out_fd, int in_fd, off_t *offset, off_t count)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue