Actions
Bug #18940
openRuby Ractor fails with IOError when handling higher concurrency
Description
Reproduction server:
require 'socket'
# Set based on CPU count
CONCURRENCY = 8
server = TCPServer.new(8080)
workers = CONCURRENCY.times.map do
Ractor.new do
loop do
# receive TCPSocket
session = Ractor.recv
request = session.gets
puts request
session.print "HTTP/1.1 200\r\n"
session.print "Content-Type: text/html\r\n"
session.print "\r\n"
session.print "Hello world! Current time is #{Time.now}"
session.close
end
end
end
loop do
conn, _ = server.accept
# pass TCPSocket to one of the workers
workers.sample.send(conn, move: true)
end
run apache benchmark against code above:
ab -n 20000 -c 20 http://localhost:8080/
or run using hey (https://github.com/rakyll/hey):
hey -n 20000 -c 20 http://localhost:8080/
you should see something like this on the benchmark tool side:
Summary:
Total: 32.9538 secs
Slowest: 2.6317 secs
Fastest: 0.0002 secs
Average: 0.0331 secs
Requests/sec: 606.9098
Response time histogram:
0.000 [1] |
0.263 [16968] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
0.527 [1740] |■■■■
0.790 [0] |
1.053 [0] |
1.316 [0] |
1.579 [0] |
1.842 [0] |
2.105 [20] |
2.369 [0] |
2.632 [6] |
Latency distribution:
10% in 0.0008 secs
25% in 0.0010 secs
50% in 0.0012 secs
75% in 0.0016 secs
90% in 0.0075 secs
95% in 0.3101 secs
99% in 0.3175 secs
Details (average, fastest, slowest):
DNS+dialup: 0.0322 secs, 0.0002 secs, 2.6317 secs
DNS-lookup: 0.0006 secs, 0.0000 secs, 0.0127 secs
req write: 0.0001 secs, 0.0000 secs, 0.0095 secs
resp wait: 0.0007 secs, 0.0000 secs, 0.0140 secs
resp read: 0.0001 secs, 0.0000 secs, 0.0088 secs
Status code distribution:
[200] 18735 responses
Error distribution:
[1231] Get "http://localhost:8080/": dial tcp [::1]:8080: connect: connection refused
[16] Get "http://localhost:8080/": dial tcp [::1]:8080: connect: connection reset by peer
[1] Get "http://localhost:8080/": net/http: HTTP/1.x transport connection broken: unexpected EOF
[1] Get "http://localhost:8080/": read tcp 127.0.0.1:57078->127.0.0.1:8080: read: connection reset by peer
[1] Get "http://localhost:8080/": read tcp [::1]:57054->[::1]:8080: read: connection reset by peer
[1] Get "http://localhost:8080/": read tcp [::1]:57058->[::1]:8080: read: connection reset by peer
[1] Get "http://localhost:8080/": read tcp [::1]:57059->[::1]:8080: read: connection reset by peer
[1] Get "http://localhost:8080/": read tcp [::1]:57062->[::1]:8080: read: connection reset by peer
[1] Get "http://localhost:8080/": read tcp [::1]:57067->[::1]:8080: read: connection reset by peer
[1] Get "http://localhost:8080/": read tcp [::1]:57068->[::1]:8080: read: connection reset by peer
[1] Get "http://localhost:8080/": read tcp [::1]:57069->[::1]:8080: read: connection reset by peer
[1] Get "http://localhost:8080/": read tcp [::1]:57070->[::1]:8080: read: connection reset by peer
[1] Get "http://localhost:8080/": read tcp [::1]:57071->[::1]:8080: read: connection reset by peer
[1] Get "http://localhost:8080/": read tcp [::1]:57072->[::1]:8080: read: connection reset by peer
[1] Get "http://localhost:8080/": read tcp [::1]:57075->[::1]:8080: read: connection reset by peer
[1] Get "http://localhost:8080/": read tcp [::1]:57076->[::1]:8080: read: connection reset by peer
[1] Get "http://localhost:8080/": read tcp [::1]:57087->[::1]:8080: read: connection reset by peer
[1] Get "http://localhost:8080/": read tcp [::1]:57088->[::1]:8080: read: connection reset by peer
[1] Get "http://localhost:8080/": read tcp [::1]:57089->[::1]:8080: read: connection reset by peer
[1] Get "http://localhost:8080/": read tcp [::1]:57090->[::1]:8080: read: connection reset by peer
and this on the ruby process:
...
GET / HTTP/1.1
GET / HTTP/1.1
#<Thread:0x0000000100fbf6e8 run> terminated with exception (report_on_exception is true):
ractor.rb:21:in `write': GET / HTTP/1.1
uninitialized stream (IOError)
from ractor.rb:21:in `print'
from ractor.rb:21:in `block (3 levels) in <main>'
from ractor.rb:11:in `loop'
from ractor.rb:11:in `block (2 levels) in <main>'
GET / HTTP/1.1
GET / HTTP/1.1
Updated by hsbt (Hiroshi SHIBATA) about 2 years ago
- Status changed from Open to Assigned
- Assignee set to ko1 (Koichi Sasada)
Updated by brodock (Gabriel Mazetto) almost 2 years ago
There is a chance that the route problem is related to #19412
Actions
Like0
Like0Like0