Issue #9039 has been updated by Yui NARUSE.

Backport changed from 1.9.3: REJECTED, 2.0.0: REQUIRED, 2.1: REQUIRED to 1.9.3: DONTNEED, 2.0.0: DONTNEED, 2.1: DONTNEED

----------------------------------------
Bug #9039:  [PATCH] socket: avoid unnecessary ppoll/select on Linux (part 3)
https://bugs.ruby-lang.org/issues/9039#change-45416

* Author: Eric Wong
* Status: Closed
* Priority: Low
* Assignee: 
* Category: 
* Target version: 
* ruby -v: ruby 2.1.0dev (2013-10-20 trunk 43373) [x86_64-linux]
* Backport: 1.9.3: DONTNEED, 2.0.0: DONTNEED, 2.1: DONTNEED
----------------------------------------
It is safe on Linux to attempt using a socket without waiting on it in
all cases.  For some syscalls (e.g. accept/accept4), blocking on the
syscall instead of relying on select/poll allows the kernel to use
"wake-one" behavior and avoid the thundering herd problem.
This is likely safe on all other *nix-like systems, so this whitelist
can be expanded by interested parties.

This is a follow-up to r36944 and r36946

Using the following script, performance and distribution of
accepted socket between different processes is improved:
------------------------------8<------------------------------
require 'socket'
usage = "Usage: #$0 SOCKET_PATH"
path = ARGV.shift or abort usage
s = UNIXServer.new(path)

 # cleanup after ourselves
main_pid = $$
at_exit { File.unlink(path) if $$ == main_pid }

$stderr.sync = $stdout.sync = true
nproc = 16
stop = Time.now + 10
pipe = IO.pipe
pids = nproc.times.map do
  fork do
    pipe[0].close
    $stdout.reopen(pipe[1])
    loop do
      s.accept.close
      $stdout.syswrite "#$$\n"
    end
  end
end
pipe[1].close

 # show the number of sockets accepted by each pid
spid = Process.spawn("sort | uniq -c | sort -k1,1n", in: pipe[0])

sleep 1 # wait for processes to spin up
UNIXSocket.new(path).close until Time.now > stop
pids.each { |x| Process.kill(:TERM, x) }
s.close
Process.waitall
------------------------------8<------------------------------

  count   PID
  -----------
before:
  61166 26903
  62257 26948
  62320 26930
  62839 26945
  63084 26921
  63273 26933
  63523 26912
  63690 26939
  64051 26909
  64284 26915
  64846 26927
  64959 26924
  65157 26936
  65477 26906
  65541 26942
  66355 26918
after:
  72350 26550
  73074 26544
  73377 26553
  73457 26559
  73540 26580
  73920 26562
  74105 26541
  74109 26574
  74182 26577
  74465 26535
  74509 26556
  74672 26538
  74974 26565
  75329 26568
  75435 26547
  75565 26571

So the difference is visible in both the number of accepted sockets
and also the difference between the max/min per-process accept counts

  before: 66355 - 61166 = 5189
   after: 75565 - 72350 = 3215

(Smaller difference is better, and the difference will probably
 be even smaller on servers which do processing on the socket)


---Files--------------------------------
0001-socket-avoid-unnecessary-ppoll-select-on-Linux-part-.patch (5.49 KB)


-- 
http://bugs.ruby-lang.org/