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

ruby-changes:39032

From: normal <ko1@a...>
Date: Fri, 3 Jul 2015 07:23:01 +0900 (JST)
Subject: [ruby-changes:39032] normal:r51113 (trunk): delay `exception: false' checks for minor speedup

normal	2015-07-03 07:22:14 +0900 (Fri, 03 Jul 2015)

  New Revision: 51113

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=51113

  Log:
    delay `exception: false' checks for minor speedup
    
    Delay hash lookups until we are about to hit an exception.  This
    gives a minor speedup ratio of 2-3% in the new bm_io_nonblock_noex
    benchmark as well as reducing code.
    
    * benchmark/bm_io_nonblock_noex.rb: new benchmark
    * ext/openssl/ossl_ssl.c (no_exception_p): new function
      (ossl_start_ssl): adjust for no_exception_p
      (ossl_ssl_connect): adjust ossl_start_ssl call
      (ossl_ssl_connect_nonblock): ditto
      (ossl_ssl_accept): ditto
      (ossl_ssl_accept_nonblock): ditto
      (ossl_ssl_read_internal): adjust for no_exception_p
      (ossl_ssl_write_internal): ditto
      (ossl_ssl_write): adjust ossl_write_internal call
      (ossl_ssl_write_nonblock): ditto
    * ext/stringio/stringio.c (strio_read_nonblock):
      delay exception check
    * io.c (no_exception_p): new function
      (io_getpartial): call no_exception_p
      (io_readpartial): adjust for io_getpartial
      (get_kwargs_exception): remove
      (io_read_nonblock): adjust for io_getpartial,
      check no_exception_p on EOF
      (io_write_nonblock): call no_exception_p
      (rb_io_write_nonblock): do not check `exception: false'
      (argf_getpartial): adjust for io_getpartial
      [ruby-core:69778] [Feature #11318]

  Added files:
    trunk/benchmark/bm_io_nonblock_noex.rb
  Modified files:
    trunk/ChangeLog
    trunk/ext/openssl/ossl_ssl.c
    trunk/ext/stringio/stringio.c
    trunk/io.c
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 51112)
+++ ChangeLog	(revision 51113)
@@ -1,3 +1,29 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Fri Jul  3 07:21:06 2015  Eric Wong  <e@8...>
+
+	* benchmark/bm_io_nonblock_noex.rb: new benchmark
+	* ext/openssl/ossl_ssl.c (no_exception_p): new function
+	  (ossl_start_ssl): adjust for no_exception_p
+	  (ossl_ssl_connect): adjust ossl_start_ssl call
+	  (ossl_ssl_connect_nonblock): ditto
+	  (ossl_ssl_accept): ditto
+	  (ossl_ssl_accept_nonblock): ditto
+	  (ossl_ssl_read_internal): adjust for no_exception_p
+	  (ossl_ssl_write_internal): ditto
+	  (ossl_ssl_write): adjust ossl_write_internal call
+	  (ossl_ssl_write_nonblock): ditto
+	* ext/stringio/stringio.c (strio_read_nonblock):
+	  delay exception check
+	* io.c (no_exception_p): new function
+	  (io_getpartial): call no_exception_p
+	  (io_readpartial): adjust for io_getpartial
+	  (get_kwargs_exception): remove
+	  (io_read_nonblock): adjust for io_getpartial,
+	  check no_exception_p on EOF
+	  (io_write_nonblock): call no_exception_p
+	  (rb_io_write_nonblock): do not check `exception: false'
+	  (argf_getpartial): adjust for io_getpartial
+	  [ruby-core:69778] [Feature #11318]
+
 Fri Jul  3 07:13:11 2015  Nobuyoshi Nakada  <nobu@r...>
 
 	* dir.c (replace_real_basename): Win32 API does not set errno, get
Index: io.c
===================================================================
--- io.c	(revision 51112)
+++ io.c	(revision 51113)
@@ -2482,8 +2482,18 @@ read_internal_call(VALUE arg) https://github.com/ruby/ruby/blob/trunk/io.c#L2482
     return Qundef;
 }
 
+static int
+no_exception_p(VALUE opts)
+{
+    VALUE except;
+    ID id = id_exception;
+
+    rb_get_kwargs(opts, &id, 0, 1, &except);
+    return except == Qfalse;
+}
+
 static VALUE
-io_getpartial(int argc, VALUE *argv, VALUE io, int nonblock, int no_exception)
+io_getpartial(int argc, VALUE *argv, VALUE io, VALUE opts, int nonblock)
 {
     rb_io_t *fptr;
     VALUE length, str;
@@ -2523,7 +2533,7 @@ io_getpartial(int argc, VALUE *argv, VAL https://github.com/ruby/ruby/blob/trunk/io.c#L2533
             if (!nonblock && rb_io_wait_readable(fptr->fd))
                 goto again;
             if (nonblock && (errno == EWOULDBLOCK || errno == EAGAIN)) {
-                if (no_exception)
+                if (no_exception_p(opts))
                     return sym_wait_readable;
                 else
 		    rb_readwrite_sys_fail(RB_IO_WAIT_READABLE, "read would block");
@@ -2603,25 +2613,12 @@ io_readpartial(int argc, VALUE *argv, VA https://github.com/ruby/ruby/blob/trunk/io.c#L2613
 {
     VALUE ret;
 
-    ret = io_getpartial(argc, argv, io, 0, 0);
+    ret = io_getpartial(argc, argv, io, Qnil, 0);
     if (NIL_P(ret))
         rb_eof_error();
     return ret;
 }
 
-static VALUE
-get_kwargs_exception(VALUE opts)
-{
-    static ID ids[1];
-    VALUE except;
-
-    if (!ids[0])
-	ids[0] = id_exception;
-
-    rb_get_kwargs(opts, ids, 0, 1, &except);
-    return except;
-}
-
 /*
  *  call-seq:
  *     ios.read_nonblock(maxlen)              -> string
@@ -2676,19 +2673,14 @@ get_kwargs_exception(VALUE opts) https://github.com/ruby/ruby/blob/trunk/io.c#L2673
 static VALUE
 io_read_nonblock(int argc, VALUE *argv, VALUE io)
 {
-    VALUE ret;
-    VALUE opts = Qnil;
-    int no_exception = 0;
+    VALUE ret, opts;
 
     rb_scan_args(argc, argv, "11:", NULL, NULL, &opts);
 
-    if (!NIL_P(opts) && Qfalse == get_kwargs_exception(opts))
-	no_exception = 1;
-
-    ret = io_getpartial(argc, argv, io, 1, no_exception);
+    ret = io_getpartial(argc, argv, io, opts, 1);
 
     if (NIL_P(ret)) {
-	if (no_exception)
+	if (no_exception_p(opts))
 	    return Qnil;
 	else
 	    rb_eof_error();
@@ -2697,7 +2689,7 @@ io_read_nonblock(int argc, VALUE *argv, https://github.com/ruby/ruby/blob/trunk/io.c#L2689
 }
 
 static VALUE
-io_write_nonblock(VALUE io, VALUE str, int no_exception)
+io_write_nonblock(VALUE io, VALUE str, VALUE opts)
 {
     rb_io_t *fptr;
     long n;
@@ -2717,7 +2709,7 @@ io_write_nonblock(VALUE io, VALUE str, i https://github.com/ruby/ruby/blob/trunk/io.c#L2709
 
     if (n == -1) {
         if (errno == EWOULDBLOCK || errno == EAGAIN) {
-	    if (no_exception) {
+	    if (no_exception_p(opts)) {
 		return sym_wait_writable;
 	    }
 	    else {
@@ -2791,16 +2783,11 @@ io_write_nonblock(VALUE io, VALUE str, i https://github.com/ruby/ruby/blob/trunk/io.c#L2783
 static VALUE
 rb_io_write_nonblock(int argc, VALUE *argv, VALUE io)
 {
-    VALUE str;
-    VALUE opts = Qnil;
-    int no_exceptions = 0;
+    VALUE str, opts;
 
     rb_scan_args(argc, argv, "10:", &str, &opts);
 
-    if (!NIL_P(opts) && Qfalse == get_kwargs_exception(opts))
-	no_exceptions = 1;
-
-    return io_write_nonblock(io, str, no_exceptions);
+    return io_write_nonblock(io, str, opts);
 }
 
 /*
@@ -11218,7 +11205,7 @@ argf_getpartial(int argc, VALUE *argv, V https://github.com/ruby/ruby/blob/trunk/io.c#L11205
 			 RUBY_METHOD_FUNC(0), Qnil, rb_eEOFError, (VALUE)0);
     }
     else {
-        tmp = io_getpartial(argc, argv, ARGF.current_file, nonblock, 0);
+        tmp = io_getpartial(argc, argv, ARGF.current_file, Qnil, nonblock);
     }
     if (NIL_P(tmp)) {
         if (ARGF.next_p == -1) {
Index: ext/openssl/ossl_ssl.c
===================================================================
--- ext/openssl/ossl_ssl.c	(revision 51112)
+++ ext/openssl/ossl_ssl.c	(revision 51113)
@@ -1273,14 +1273,23 @@ read_would_block(int nonblock) https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_ssl.c#L1273
     }
 }
 
+static int
+no_exception_p(VALUE opts)
+{
+    if (RB_TYPE_P(opts, T_HASH) &&
+          rb_hash_lookup2(opts, sym_exception, Qundef) == Qfalse)
+	return 1;
+    return 0;
+}
+
 static VALUE
-ossl_start_ssl(VALUE self, int (*func)(), const char *funcname,
-		int nonblock, int no_exception)
+ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, VALUE opts)
 {
     SSL *ssl;
     rb_io_t *fptr;
     int ret, ret2;
     VALUE cb_state;
+    int nonblock = opts != Qfalse;
 
     rb_ivar_set(self, ID_callback_state, Qnil);
 
@@ -1299,12 +1308,12 @@ ossl_start_ssl(VALUE self, int (*func)() https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_ssl.c#L1308
 
 	switch((ret2 = ssl_get_error(ssl, ret))){
 	case SSL_ERROR_WANT_WRITE:
-            if (no_exception) { return sym_wait_writable; }
+            if (no_exception_p(opts)) { return sym_wait_writable; }
             write_would_block(nonblock);
             rb_io_wait_writable(FPTR_TO_FD(fptr));
             continue;
 	case SSL_ERROR_WANT_READ:
-            if (no_exception) { return sym_wait_readable; }
+            if (no_exception_p(opts)) { return sym_wait_readable; }
             read_would_block(nonblock);
             rb_io_wait_readable(FPTR_TO_FD(fptr));
             continue;
@@ -1330,15 +1339,8 @@ static VALUE https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_ssl.c#L1339
 ossl_ssl_connect(VALUE self)
 {
     ossl_ssl_setup(self);
-    return ossl_start_ssl(self, SSL_connect, "SSL_connect", 0, 0);
-}
 
-static int
-get_no_exception(VALUE opts)
-{
-    if (!NIL_P(opts) && Qfalse == rb_hash_lookup2(opts, sym_exception, Qundef))
-	return 1;
-    return 0;
+    return ossl_start_ssl(self, SSL_connect, "SSL_connect", Qfalse);
 }
 
 /*
@@ -1366,14 +1368,12 @@ get_no_exception(VALUE opts) https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_ssl.c#L1368
 static VALUE
 ossl_ssl_connect_nonblock(int argc, VALUE *argv, VALUE self)
 {
-    int no_exception;
-    VALUE opts = Qnil;
-
+    VALUE opts;
     rb_scan_args(argc, argv, "0:", &opts);
-    no_exception = get_no_exception(opts);
 
     ossl_ssl_setup(self);
-    return ossl_start_ssl(self, SSL_connect, "SSL_connect", 1, no_exception);
+
+    return ossl_start_ssl(self, SSL_connect, "SSL_connect", opts);
 }
 
 /*
@@ -1387,7 +1387,8 @@ static VALUE https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_ssl.c#L1387
 ossl_ssl_accept(VALUE self)
 {
     ossl_ssl_setup(self);
-    return ossl_start_ssl(self, SSL_accept, "SSL_accept", 0, 0);
+
+    return ossl_start_ssl(self, SSL_accept, "SSL_accept", Qfalse);
 }
 
 /*
@@ -1415,14 +1416,12 @@ ossl_ssl_accept(VALUE self) https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_ssl.c#L1416
 static VALUE
 ossl_ssl_accept_nonblock(int argc, VALUE *argv, VALUE self)
 {
-    int no_exception;
-    VALUE opts = Qnil;
+    VALUE opts;
 
     rb_scan_args(argc, argv, "0:", &opts);
-    no_exception = get_no_exception(opts);
-
     ossl_ssl_setup(self);
-    return ossl_start_ssl(self, SSL_accept, "SSL_accept", 1, no_exception);
+
+    return ossl_start_ssl(self, SSL_accept, "SSL_accept", opts);
 }
 
 static VALUE
@@ -1430,14 +1429,12 @@ ossl_ssl_read_internal(int argc, VALUE * https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_ssl.c#L1429
 {
     SSL *ssl;
     int ilen, nread = 0;
-    int no_exception = 0;
     VALUE len, str;
     rb_io_t *fptr;
     VALUE opts = Qnil;
 
     if (nonblock) {
 	rb_scan_args(argc, argv, "11:", &len, &str, &opts);
-	no_exception = get_no_exception(opts);
     } else {
 	rb_scan_args(argc, argv, "11", &len, &str);
     }
@@ -1462,21 +1459,21 @@ ossl_ssl_read_internal(int argc, VALUE * https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_ssl.c#L1459
 	    case SSL_ERROR_NONE:
 		goto end;
 	    case SSL_ERROR_ZERO_RETURN:
-		if (no_exception) { return Qnil; }
+		if (no_exception_p(opts)) { return Qnil; }
 		rb_eof_error();
 	    case SSL_ERROR_WANT_WRITE:
-		if (no_exception) { return sym_wait_writable; }
+		if (no_exception_p(opts)) { return sym_wait_writable; }
                 write_would_block(nonblock);
                 rb_io_wait_writable(FPTR_TO_FD(fptr));
                 continue;
 	    case SSL_ERROR_WANT_READ:
-		if (no_exception) { return sym_wait_readable; }
+		if (no_exception_p(opts)) { return sym_wait_readable; }
                 read_would_block(nonblock);
                 rb_io_wait_readable(FPTR_TO_FD(fptr));
 		continue;
 	    case SSL_ERROR_SYSCALL:
 		if(ERR_peek_error() == 0 && nread == 0) {
-		    if (no_exception) { return Qnil; }
+		    if (no_exception_p(opts)) { return Qnil; }
 		    rb_eof_error();
 		}
 		rb_sys_fail(0);
@@ -1536,11 +1533,12 @@ ossl_ssl_read_nonblock(int argc, VALUE * https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_ssl.c#L1533
 }
 
 static VALUE
-ossl_ssl_write_internal(VALUE self, VALUE str, int nonblock, int no_exception)
+ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts)
 {
     SSL *ssl;
     int nwrite = 0;
     rb_io_t *fptr;
+    int nonblock = opts != Qfalse;
 
     StringValue(str);
     GetSSL(self, ssl);
@@ -1553,12 +1551,12 @@ ossl_ssl_write_internal(VALUE self, VALU https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_ssl.c#L1551
 	    case SSL_ERROR_NONE:
 		goto end;
 	    case SSL_ERROR_WANT_WRITE:
-		if (no_exception) { return sym_wait_writable; }
+		if (no_exception_p(opts)) { return sym_wait_writable; }
                 write_would_block(nonblock);
                 rb_io_wait_writable(FPTR_TO_FD(fptr));
                 continue;
 	    case SSL_ERROR_WANT_READ:
-		if (no_exception) { return sym_wait_readable; }
+		if (no_exception_p(opts)) { return sym_wait_readable; }
                 read_would_block(nonblock);
                 rb_io_wait_readable(FPTR_TO_FD(fptr));
                 continue;
@@ -1588,7 +1586,7 @@ ossl_ssl_write_internal(VALUE self, VALU https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_ssl.c#L1586
 static VALUE
 ossl_ssl_write(VALUE self, VALUE str)
 {
-    return ossl_ssl_write_internal(self, str, 0, 0);
+    return ossl_ssl_write_internal(self, str, Qfalse);
 }
 
 /*
@@ -1601,14 +1599,11 @@ ossl_ssl_write(VALUE self, VALUE str) https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_ssl.c#L1599
 static VALUE
 ossl_ssl_write_nonblock(int argc, VALUE *argv, VALUE self)
 {
-    VALUE str;
-    VALUE opts = Qnil;
-    int no_exception;
+    VALUE str, opts;
 
     rb_scan_args(argc, argv, "1:", &str, &opts);
-    no_exception = get_no_exception(opts);
 
-    return ossl_ssl_write_internal(self, str, 1, no_exception);
+    return ossl_ssl_write_internal(self, str, opts);
 }
 
 /*
Index: ext/stringio/stringio.c
===================================================================
--- ext/stringio/stringio.c	(revision 51112)
+++ ext/stringio/stringio.c	(revision 51113)
@@ -1359,20 +1359,17 @@ static VALUE https://github.com/ruby/ruby/blob/trunk/ext/stringio/stringio.c#L1359
 strio_read_nonblock(int argc, VALUE *argv, VALUE self)
 {
     VALUE opts = Qnil, val;
-    int no_exception = 0;
 
     rb_scan_args(argc, argv, "11:", NULL, NULL, &opts);
 
     if (!NIL_P(opts)) {
 	argc--;
-
-	if (Qfalse == rb_hash_aref(opts, sym_exception))
-	    no_exception = 1;
     }
 
     val = strio_read(argc, argv, self);
     if (NIL_P(val)) {
-	if (no_exception)
+	if (!NIL_P(opts) &&
+	      rb_hash_lookup2(opts, sym_exception, Qundef) == Qfalse)
 	    return Qnil;
 	else
 	    rb_eof_error();
Index: benchmark/bm_io_nonblock_noex.rb
===================================================================
--- benchmark/bm_io_nonblock_noex.rb	(revision 0)
+++ benchmark/bm_io_nonblock_noex.rb	(revision 51113)
@@ -0,0 +1,22 @@ https://github.com/ruby/ruby/blob/trunk/benchmark/bm_io_nonblock_noex.rb#L1
+nr = 1_000_000
+i = 0
+msg = '.'
+buf = '.'
+noex = { exception: false }
+begin
+  r, w = IO.pipe
+  while i < nr
+    i += 1
+    w.write_nonblock(msg, noex)
+    r.read_nonblock(1, buf, noex)
+  end
+rescue ArgumentError # old Rubies
+  while i < nr
+    i += 1
+    w.write_nonblock(msg)
+    r.read_nonblock(1, buf)
+  end
+ensure
+  r.close
+  w.close
+end

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

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