Bug #9039

[PATCH] socket: avoid unnecessary ppoll/select on Linux (part 3)

Added by Eric Wong 6 months ago. Updated about 1 month ago.

[ruby-core:57950]
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

Description

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
mainpid = $$
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)

0001-socket-avoid-unnecessary-ppoll-select-on-Linux-part-.patch Magnifier (5.49 KB) Eric Wong, 10/21/2013 04:09 PM

Associated revisions

Revision 44643
Added by Akira Tanaka 3 months ago

  • ext/socket: Avoid unnecessary ppoll/select on Linux. Patch by Eric Wong. [Bug #9039]

History

#1 Updated by Akira Tanaka 3 months ago

  • Status changed from Open to Closed
  • % Done changed from 0 to 100

Applied in changeset r44643.


  • ext/socket: Avoid unnecessary ppoll/select on Linux. Patch by Eric Wong. [Bug #9039]

#2 Updated by Usaku NAKAMURA 2 months ago

  • Backport changed from 1.9.3: UNKNOWN, 2.0.0: UNKNOWN to 1.9.3: REQUIRED, 2.0.0: REQUIRED, 2.1: REQUIRED

#3 Updated by Usaku NAKAMURA 2 months ago

  • Backport changed from 1.9.3: REQUIRED, 2.0.0: REQUIRED, 2.1: REQUIRED to 1.9.3: DONE, 2.0.0: REQUIRED, 2.1: REQUIRED

backported into ruby19_3 at r44943.

#4 Updated by Usaku NAKAMURA 2 months ago

  • Backport changed from 1.9.3: DONE, 2.0.0: REQUIRED, 2.1: REQUIRED to 1.9.3: REJECTED, 2.0.0: REQUIRED, 2.1: REQUIRED

... but reverted from ruby19_3 because it causes errors on CI.

#5 Updated by Eric Wong 2 months ago

usa@garbagecollect.jp wrote:

Issue #9039 has been updated by Usaku NAKAMURA.

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

... but reverted from ruby19_3 because it causes errors on CI.

I misfiled this as a Bug instead of Feature, so no backport was
necessary. However, I'm curious what the errors were and which version of
Linux it happened under. Thanks.

#6 Updated by Yui NARUSE about 1 month ago

  • 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

Also available in: Atom PDF