From bee5b49aece1499309b7e7bb6e8e373a1d67e4ce Mon Sep 17 00:00:00 2001 From: normal Date: Mon, 16 Nov 2015 23:40:15 +0000 Subject: socket: avoid arg parsing in rsock_s_accept_nonblock * ext/socket/init.c (rsock_s_accept_nonblock): avoid parsing args [ruby-core:71439] [Feature #11339] * ext/socket/rubysocket.h: adjust prototype * ext/socket/socket.c (sock_accept_nonblock): make private * ext/socket/tcpserver.c (tcp_accept_nonblock): ditto * ext/socket/unixserver.c (unix_accept_nonblock): ditto * ext/socket/lib/socket.rb (Socket#accept_nonblock): implement as wrapper, move RDoc (TCPServer#accept_nonblock): ditto (UNIXServer#accept_nonblock): ditto target 0: a (ruby 2.3.0dev (2015-11-12 trunk 52550) [x86_64-linux]) target 1: b (ruby 2.3.0dev (2015-11-12 avoid-kwarg-capi 52550) [x86_64-linux] ----------------------------------------------------------- accept_nonblock require 'tempfile' require 'socket' require 'io/wait' nr = 500000 Tempfile.create(%w(accept_nonblock .sock)) do |tmp| path = tmp.path File.unlink(path) s = UNIXServer.new(path) addr = Socket.sockaddr_un(path).freeze nr.times do s.accept_nonblock(exception: false) c = UNIXSocket.new(path) s.wait_readable s.accept_nonblock(exception: false).close c.close end end ----------------------------------------------------------- raw data: [["accept_nonblock", [[4.807877402752638, 4.930681671947241, 4.738454818725586, 4.69268161803484, 4.684675686061382], [4.253904823213816, 4.255124930292368, 4.295955188572407, 4.248479191213846, 4.213303029537201]]]] Elapsed time: 45.123040065 (sec) ----------------------------------------------------------- benchmark results: minimum results in each 5 measurements. Execution time (sec) name a b accept_nonblock 4.685 4.213 Speedup ratio: compare with the result of `a' (greater is better) name b accept_nonblock 1.112 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52601 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/socket/unixserver.c | 47 +++++++---------------------------------------- 1 file changed, 7 insertions(+), 40 deletions(-) (limited to 'ext/socket/unixserver.c') diff --git a/ext/socket/unixserver.c b/ext/socket/unixserver.c index 532d951c93..799dcffb00 100644 --- a/ext/socket/unixserver.c +++ b/ext/socket/unixserver.c @@ -57,45 +57,9 @@ unix_accept(VALUE sock) (struct sockaddr*)&from, &fromlen); } -/* - * call-seq: - * unixserver.accept_nonblock([options]) => unixsocket - * - * Accepts an incoming connection using accept(2) after - * O_NONBLOCK is set for the underlying file descriptor. - * It returns an accepted UNIXSocket for the incoming connection. - * - * === Example - * require 'socket' - * serv = UNIXServer.new("/tmp/sock") - * begin # emulate blocking accept - * sock = serv.accept_nonblock - * rescue IO::WaitReadable, Errno::EINTR - * IO.select([serv]) - * retry - * end - * # sock is an accepted socket. - * - * Refer to Socket#accept for the exceptions that may be thrown if the call - * to UNIXServer#accept_nonblock fails. - * - * UNIXServer#accept_nonblock may raise any error corresponding to accept(2) failure, - * including Errno::EWOULDBLOCK. - * - * If the exception is Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::ECONNABORTED or Errno::EPROTO, - * it is extended by IO::WaitReadable. - * So IO::WaitReadable can be used to rescue the exceptions for retrying accept_nonblock. - * - * By specifying `exception: false`, the options hash allows you to indicate - * that accept_nonblock should not raise an IO::WaitReadable exception, but - * return the symbol :wait_readable instead. - * - * === See - * * UNIXServer#accept - * * Socket#accept - */ +/* :nodoc: */ static VALUE -unix_accept_nonblock(int argc, VALUE *argv, VALUE sock) +unix_accept_nonblock(VALUE sock, VALUE ex) { rb_io_t *fptr; struct sockaddr_un from; @@ -103,7 +67,7 @@ unix_accept_nonblock(int argc, VALUE *argv, VALUE sock) GetOpenFile(sock, fptr); fromlen = (socklen_t)sizeof(from); - return rsock_s_accept_nonblock(argc, argv, rb_cUNIXSocket, fptr, + return rsock_s_accept_nonblock(rb_cUNIXSocket, ex, fptr, (struct sockaddr *)&from, &fromlen); } @@ -152,7 +116,10 @@ rsock_init_unixserver(void) rb_cUNIXServer = rb_define_class("UNIXServer", rb_cUNIXSocket); rb_define_method(rb_cUNIXServer, "initialize", unix_svr_init, 1); rb_define_method(rb_cUNIXServer, "accept", unix_accept, 0); - rb_define_method(rb_cUNIXServer, "accept_nonblock", unix_accept_nonblock, -1); + + rb_define_private_method(rb_cUNIXServer, + "__accept_nonblock", unix_accept_nonblock, 1); + rb_define_method(rb_cUNIXServer, "sysaccept", unix_sysaccept, 0); rb_define_method(rb_cUNIXServer, "listen", rsock_sock_listen, 1); /* in socket.c */ #endif -- cgit v1.2.3