polyphony 0.63 → 0.67
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +1 -1
- data/CHANGELOG.md +19 -0
- data/Gemfile.lock +1 -1
- data/TODO.md +10 -40
- data/bin/pdbg +30 -0
- data/examples/core/await.rb +9 -1
- data/ext/polyphony/backend_common.c +14 -1
- data/ext/polyphony/backend_common.h +3 -1
- data/ext/polyphony/backend_io_uring.c +84 -24
- data/ext/polyphony/backend_io_uring_context.c +42 -0
- data/ext/polyphony/backend_io_uring_context.h +6 -9
- data/ext/polyphony/backend_libev.c +85 -39
- data/ext/polyphony/fiber.c +20 -0
- data/ext/polyphony/polyphony.c +2 -0
- data/ext/polyphony/polyphony.h +5 -2
- data/ext/polyphony/queue.c +1 -1
- data/ext/polyphony/runqueue.c +7 -3
- data/ext/polyphony/runqueue.h +4 -3
- data/ext/polyphony/runqueue_ring_buffer.c +25 -14
- data/ext/polyphony/runqueue_ring_buffer.h +2 -0
- data/ext/polyphony/thread.c +2 -8
- data/lib/polyphony.rb +6 -0
- data/lib/polyphony/debugger/server.rb +137 -0
- data/lib/polyphony/extensions/debug.rb +1 -1
- data/lib/polyphony/extensions/fiber.rb +40 -33
- data/lib/polyphony/extensions/io.rb +6 -2
- data/lib/polyphony/extensions/openssl.rb +8 -2
- data/lib/polyphony/extensions/socket.rb +15 -10
- data/lib/polyphony/version.rb +1 -1
- data/test/helper.rb +6 -4
- data/test/stress.rb +6 -2
- data/test/test_backend.rb +13 -4
- data/test/test_fiber.rb +33 -9
- data/test/test_global_api.rb +9 -4
- data/test/test_io.rb +2 -0
- data/test/test_socket.rb +14 -11
- data/test/test_thread.rb +3 -0
- data/test/test_thread_pool.rb +1 -1
- data/test/test_throttler.rb +2 -2
- data/test/test_timer.rb +5 -3
- metadata +4 -2
data/lib/polyphony/version.rb
CHANGED
data/test/helper.rb
CHANGED
|
@@ -15,6 +15,8 @@ require 'minitest/reporters'
|
|
|
15
15
|
|
|
16
16
|
::Exception.__disable_sanitized_backtrace__ = true
|
|
17
17
|
|
|
18
|
+
IS_LINUX = RUBY_PLATFORM =~ /linux/
|
|
19
|
+
|
|
18
20
|
# Minitest::Reporters.use! [
|
|
19
21
|
# Minitest::Reporters::SpecReporter.new
|
|
20
22
|
# ]
|
|
@@ -44,10 +46,6 @@ end
|
|
|
44
46
|
class MiniTest::Test
|
|
45
47
|
def setup
|
|
46
48
|
# trace "* setup #{self.name}"
|
|
47
|
-
if Fiber.current.children.size > 0
|
|
48
|
-
puts "Children left: #{Fiber.current.children.inspect}"
|
|
49
|
-
exit!
|
|
50
|
-
end
|
|
51
49
|
Fiber.current.setup_main_fiber
|
|
52
50
|
Fiber.current.instance_variable_set(:@auto_watcher, nil)
|
|
53
51
|
Thread.current.backend.finalize
|
|
@@ -58,6 +56,10 @@ class MiniTest::Test
|
|
|
58
56
|
def teardown
|
|
59
57
|
# trace "* teardown #{self.name}"
|
|
60
58
|
Fiber.current.shutdown_all_children
|
|
59
|
+
if Fiber.current.children.size > 0
|
|
60
|
+
puts "Children left after #{self.name}: #{Fiber.current.children.inspect}"
|
|
61
|
+
exit!
|
|
62
|
+
end
|
|
61
63
|
Fiber.current.instance_variable_set(:@auto_watcher, nil)
|
|
62
64
|
rescue => e
|
|
63
65
|
puts e
|
data/test/stress.rb
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
count = ARGV[0] ? ARGV[0].to_i : 100
|
|
4
|
+
test_name = ARGV[1]
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
$test_cmd = +'ruby test/run.rb'
|
|
7
|
+
if test_name
|
|
8
|
+
$test_cmd << " --name #{test_name}"
|
|
9
|
+
end
|
|
6
10
|
|
|
7
11
|
def run_test(count)
|
|
8
12
|
puts "#{count}: running tests..."
|
|
9
13
|
# sleep 1
|
|
10
|
-
system(
|
|
14
|
+
system($test_cmd)
|
|
11
15
|
puts
|
|
12
16
|
|
|
13
17
|
return if $?.exitstatus == 0
|
data/test/test_backend.rb
CHANGED
|
@@ -26,7 +26,7 @@ class BackendTest < MiniTest::Test
|
|
|
26
26
|
@backend.sleep 0.01
|
|
27
27
|
count += 1
|
|
28
28
|
}.await
|
|
29
|
-
assert_in_range 0.02..0.
|
|
29
|
+
assert_in_range 0.02..0.06, Time.now - t0 if IS_LINUX
|
|
30
30
|
assert_equal 3, count
|
|
31
31
|
end
|
|
32
32
|
|
|
@@ -243,6 +243,8 @@ class BackendTest < MiniTest::Test
|
|
|
243
243
|
end
|
|
244
244
|
|
|
245
245
|
def test_timer_loop
|
|
246
|
+
skip unless IS_LINUX
|
|
247
|
+
|
|
246
248
|
i = 0
|
|
247
249
|
f = spin do
|
|
248
250
|
@backend.timer_loop(0.01) { i += 1 }
|
|
@@ -257,6 +259,8 @@ class BackendTest < MiniTest::Test
|
|
|
257
259
|
end
|
|
258
260
|
|
|
259
261
|
def test_timeout
|
|
262
|
+
skip unless IS_LINUX
|
|
263
|
+
|
|
260
264
|
buffer = []
|
|
261
265
|
assert_raises(Polyphony::TimeoutException) do
|
|
262
266
|
@backend.timeout(0.01, Polyphony::TimeoutException) do
|
|
@@ -288,6 +292,8 @@ class BackendTest < MiniTest::Test
|
|
|
288
292
|
end
|
|
289
293
|
|
|
290
294
|
def test_nested_timeout
|
|
295
|
+
skip unless IS_LINUX
|
|
296
|
+
|
|
291
297
|
buffer = []
|
|
292
298
|
assert_raises(MyTimeoutException) do
|
|
293
299
|
@backend.timeout(0.01, MyTimeoutException) do
|
|
@@ -347,8 +353,8 @@ class BackendTest < MiniTest::Test
|
|
|
347
353
|
|
|
348
354
|
|
|
349
355
|
def test_splice_chunks
|
|
350
|
-
body = 'abcd' *
|
|
351
|
-
chunk_size =
|
|
356
|
+
body = 'abcd' * 4
|
|
357
|
+
chunk_size = 12
|
|
352
358
|
|
|
353
359
|
buf = +''
|
|
354
360
|
r, w = IO.pipe
|
|
@@ -373,7 +379,7 @@ class BackendTest < MiniTest::Test
|
|
|
373
379
|
w.close
|
|
374
380
|
reader.await
|
|
375
381
|
|
|
376
|
-
expected = "Content-Type: foo\r\n\r\n#{
|
|
382
|
+
expected = "Content-Type: foo\r\n\r\n#{12.to_s(16)}\r\n#{body[0..11]}\r\n#{4.to_s(16)}\r\n#{body[12..15]}\r\n0\r\n\r\n"
|
|
377
383
|
assert_equal expected, buf
|
|
378
384
|
ensure
|
|
379
385
|
o.close
|
|
@@ -394,6 +400,9 @@ class BackendTest < MiniTest::Test
|
|
|
394
400
|
assert_equal count, GC.count
|
|
395
401
|
sleep 0.05
|
|
396
402
|
assert_equal count, GC.count
|
|
403
|
+
|
|
404
|
+
return unless IS_LINUX
|
|
405
|
+
|
|
397
406
|
# The idle tasks are ran at most once per fiber switch, before the backend
|
|
398
407
|
# is polled. Therefore, the second sleep will not have triggered a GC, since
|
|
399
408
|
# only 0.05s have passed since the gc period was set.
|
data/test/test_fiber.rb
CHANGED
|
@@ -46,7 +46,7 @@ class FiberTest < MiniTest::Test
|
|
|
46
46
|
def test_await_dead_children
|
|
47
47
|
f1 = spin { :foo }
|
|
48
48
|
f2 = spin { :bar }
|
|
49
|
-
|
|
49
|
+
4.times { snooze }
|
|
50
50
|
|
|
51
51
|
assert_equal [:foo, :bar], Fiber.await(f1, f2)
|
|
52
52
|
end
|
|
@@ -67,10 +67,12 @@ class FiberTest < MiniTest::Test
|
|
|
67
67
|
}
|
|
68
68
|
Fiber.await(f2, f3)
|
|
69
69
|
assert_equal [:foo, :bar, :baz], buffer
|
|
70
|
-
assert_equal
|
|
70
|
+
assert_equal [f1], Fiber.current.children
|
|
71
|
+
Fiber.current.reap_dead_children
|
|
72
|
+
assert_equal [], Fiber.current.children
|
|
71
73
|
end
|
|
72
74
|
|
|
73
|
-
def test_await_from_multiple_fibers_with_interruption
|
|
75
|
+
def test_await_from_multiple_fibers_with_interruption
|
|
74
76
|
buffer = []
|
|
75
77
|
f1 = spin {
|
|
76
78
|
sleep 0.02
|
|
@@ -91,6 +93,8 @@ class FiberTest < MiniTest::Test
|
|
|
91
93
|
f1.stop
|
|
92
94
|
|
|
93
95
|
snooze
|
|
96
|
+
assert_equal [f1, f2, f3], Fiber.current.children
|
|
97
|
+
Fiber.current.reap_dead_children
|
|
94
98
|
assert_equal [], Fiber.current.children
|
|
95
99
|
end
|
|
96
100
|
|
|
@@ -563,10 +567,10 @@ class FiberTest < MiniTest::Test
|
|
|
563
567
|
end
|
|
564
568
|
|
|
565
569
|
snooze
|
|
566
|
-
child.monitor
|
|
570
|
+
child.monitor(Fiber.current)
|
|
567
571
|
spin { child << :foo }
|
|
568
572
|
|
|
569
|
-
msg =
|
|
573
|
+
msg = Fiber.current.monitor_mailbox.shift
|
|
570
574
|
assert_equal [child, :foo], msg
|
|
571
575
|
end
|
|
572
576
|
|
|
@@ -578,14 +582,14 @@ class FiberTest < MiniTest::Test
|
|
|
578
582
|
end
|
|
579
583
|
|
|
580
584
|
snooze
|
|
581
|
-
child.monitor
|
|
585
|
+
child.monitor(Fiber.current)
|
|
582
586
|
spin { child << :foo }
|
|
583
587
|
snooze
|
|
584
588
|
|
|
585
|
-
child.unmonitor
|
|
589
|
+
child.unmonitor(Fiber.current)
|
|
586
590
|
|
|
587
|
-
Fiber.current << :bar
|
|
588
|
-
msg =
|
|
591
|
+
Fiber.current.monitor_mailbox << :bar
|
|
592
|
+
msg = Fiber.current.monitor_mailbox.shift
|
|
589
593
|
assert_equal :bar, msg
|
|
590
594
|
end
|
|
591
595
|
|
|
@@ -598,6 +602,7 @@ class FiberTest < MiniTest::Test
|
|
|
598
602
|
|
|
599
603
|
f.stop
|
|
600
604
|
snooze
|
|
605
|
+
Fiber.current.reap_dead_children
|
|
601
606
|
assert_equal [], Fiber.current.children
|
|
602
607
|
end
|
|
603
608
|
|
|
@@ -1218,4 +1223,23 @@ class GracefulTerminationTest < MiniTest::Test
|
|
|
1218
1223
|
|
|
1219
1224
|
assert_equal [1, 2], buffer
|
|
1220
1225
|
end
|
|
1226
|
+
end
|
|
1227
|
+
|
|
1228
|
+
class DebugTest < MiniTest::Test
|
|
1229
|
+
def test_parking
|
|
1230
|
+
buf = []
|
|
1231
|
+
f = spin do
|
|
1232
|
+
3.times { |i| snooze; buf << i }
|
|
1233
|
+
end
|
|
1234
|
+
assert_nil f.__parked__?
|
|
1235
|
+
f.__park__
|
|
1236
|
+
assert_equal true, f.__parked__?
|
|
1237
|
+
10.times { snooze }
|
|
1238
|
+
assert_equal [], buf
|
|
1239
|
+
|
|
1240
|
+
f.__unpark__
|
|
1241
|
+
assert_nil f.__parked__?
|
|
1242
|
+
10.times { snooze }
|
|
1243
|
+
assert_equal [0, 1, 2], buf
|
|
1244
|
+
end
|
|
1221
1245
|
end
|
data/test/test_global_api.rb
CHANGED
|
@@ -137,7 +137,7 @@ class MoveOnAfterTest < MiniTest::Test
|
|
|
137
137
|
t1 = Time.now
|
|
138
138
|
|
|
139
139
|
assert_nil v
|
|
140
|
-
assert_in_range 0.014..0.02, t1 - t0
|
|
140
|
+
assert_in_range 0.014..0.02, t1 - t0 if IS_LINUX
|
|
141
141
|
end
|
|
142
142
|
|
|
143
143
|
def test_move_on_after_without_block
|
|
@@ -152,6 +152,8 @@ class MoveOnAfterTest < MiniTest::Test
|
|
|
152
152
|
end
|
|
153
153
|
|
|
154
154
|
def test_nested_move_on_after
|
|
155
|
+
skip unless IS_LINUX
|
|
156
|
+
|
|
155
157
|
t0 = Time.now
|
|
156
158
|
o = move_on_after(0.01, with_value: 1) do
|
|
157
159
|
move_on_after(0.02, with_value: 2) do
|
|
@@ -210,7 +212,7 @@ class CancelAfterTest < MiniTest::Test
|
|
|
210
212
|
sleep 0.007
|
|
211
213
|
end
|
|
212
214
|
t1 = Time.now
|
|
213
|
-
assert_in_range 0.014..0.024, t1 - t0
|
|
215
|
+
assert_in_range 0.014..0.024, t1 - t0 if IS_LINUX
|
|
214
216
|
end
|
|
215
217
|
|
|
216
218
|
class CustomException < Exception
|
|
@@ -373,6 +375,7 @@ class SpinScopeTest < MiniTest::Test
|
|
|
373
375
|
buffer << e.message
|
|
374
376
|
end
|
|
375
377
|
10.times { snooze }
|
|
378
|
+
Fiber.current.reap_dead_children
|
|
376
379
|
assert_equal 0, Fiber.current.children.size
|
|
377
380
|
assert_equal ['foobar'], buffer
|
|
378
381
|
end
|
|
@@ -399,7 +402,7 @@ class ThrottledLoopTest < MiniTest::Test
|
|
|
399
402
|
end
|
|
400
403
|
f.await
|
|
401
404
|
t1 = Time.now
|
|
402
|
-
assert_in_range 0.075..0.15, t1 - t0
|
|
405
|
+
assert_in_range 0.075..0.15, t1 - t0 if IS_LINUX
|
|
403
406
|
assert_equal [1, 2, 3, 4, 5], buffer
|
|
404
407
|
end
|
|
405
408
|
end
|
|
@@ -415,6 +418,8 @@ class GlobalAPIEtcTest < MiniTest::Test
|
|
|
415
418
|
end
|
|
416
419
|
|
|
417
420
|
def test_every
|
|
421
|
+
skip unless IS_LINUX
|
|
422
|
+
|
|
418
423
|
buffer = []
|
|
419
424
|
t0 = Time.now
|
|
420
425
|
f = spin do
|
|
@@ -429,7 +434,7 @@ class GlobalAPIEtcTest < MiniTest::Test
|
|
|
429
434
|
t0 = Time.now
|
|
430
435
|
sleep 0.1
|
|
431
436
|
elapsed = Time.now - t0
|
|
432
|
-
assert (0.05..0.15).include? elapsed
|
|
437
|
+
assert (0.05..0.15).include? elapsed if IS_LINUX
|
|
433
438
|
|
|
434
439
|
f = spin { sleep }
|
|
435
440
|
snooze
|
data/test/test_io.rb
CHANGED
data/test/test_socket.rb
CHANGED
|
@@ -158,19 +158,22 @@ class SocketTest < MiniTest::Test
|
|
|
158
158
|
end
|
|
159
159
|
end
|
|
160
160
|
|
|
161
|
-
|
|
162
|
-
|
|
161
|
+
if IS_LINUX
|
|
162
|
+
class HTTPClientTest < MiniTest::Test
|
|
163
163
|
|
|
164
|
-
|
|
165
|
-
res = HTTParty.get('http://ipinfo.io/')
|
|
164
|
+
require 'json'
|
|
166
165
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
166
|
+
def test_http
|
|
167
|
+
res = HTTParty.get('http://ipinfo.io/')
|
|
168
|
+
|
|
169
|
+
response = JSON.load(res.body)
|
|
170
|
+
assert_equal 'https://ipinfo.io/missingauth', response['readme']
|
|
171
|
+
end
|
|
170
172
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
173
|
+
def test_https
|
|
174
|
+
res = HTTParty.get('https://ipinfo.io/')
|
|
175
|
+
response = JSON.load(res.body)
|
|
176
|
+
assert_equal 'https://ipinfo.io/missingauth', response['readme']
|
|
177
|
+
end
|
|
175
178
|
end
|
|
176
179
|
end
|
data/test/test_thread.rb
CHANGED
|
@@ -180,6 +180,9 @@ class ThreadTest < MiniTest::Test
|
|
|
180
180
|
assert_equal count, GC.count
|
|
181
181
|
sleep 0.05
|
|
182
182
|
assert_equal count, GC.count
|
|
183
|
+
|
|
184
|
+
return unless IS_LINUX
|
|
185
|
+
|
|
183
186
|
# The idle tasks are ran at most once per fiber switch, before the backend
|
|
184
187
|
# is polled. Therefore, the second sleep will not have triggered a GC, since
|
|
185
188
|
# only 0.05s have passed since the gc period was set.
|
data/test/test_thread_pool.rb
CHANGED
data/test/test_throttler.rb
CHANGED
|
@@ -10,7 +10,7 @@ class ThrottlerTest < MiniTest::Test
|
|
|
10
10
|
f = spin { loop { t.process { buffer << 1 } } }
|
|
11
11
|
sleep 0.2
|
|
12
12
|
f.stop
|
|
13
|
-
assert_in_range 1..
|
|
13
|
+
assert_in_range 1..4, buffer.size
|
|
14
14
|
ensure
|
|
15
15
|
t.stop
|
|
16
16
|
end
|
|
@@ -23,7 +23,7 @@ class ThrottlerTest < MiniTest::Test
|
|
|
23
23
|
end
|
|
24
24
|
sleep 0.25
|
|
25
25
|
f.stop
|
|
26
|
-
assert_in_range 2..
|
|
26
|
+
assert_in_range 2..7, buffer.size
|
|
27
27
|
ensure
|
|
28
28
|
t.stop
|
|
29
29
|
end
|
data/test/test_timer.rb
CHANGED
|
@@ -19,7 +19,7 @@ class TimerMoveOnAfterTest < MiniTest::Test
|
|
|
19
19
|
end
|
|
20
20
|
t1 = Time.now
|
|
21
21
|
|
|
22
|
-
assert_in_range 0.1..0.15, t1 - t0
|
|
22
|
+
assert_in_range 0.1..0.15, t1 - t0 if IS_LINUX
|
|
23
23
|
assert_nil v
|
|
24
24
|
end
|
|
25
25
|
|
|
@@ -31,11 +31,13 @@ class TimerMoveOnAfterTest < MiniTest::Test
|
|
|
31
31
|
end
|
|
32
32
|
t1 = Time.now
|
|
33
33
|
|
|
34
|
-
assert_in_range 0.01..0.05, t1 - t0
|
|
34
|
+
assert_in_range 0.01..0.05, t1 - t0 if IS_LINUX
|
|
35
35
|
assert_equal :bar, v
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
def test_timer_move_on_after_with_reset
|
|
39
|
+
skip unless IS_LINUX
|
|
40
|
+
|
|
39
41
|
t0 = Time.now
|
|
40
42
|
v = @timer.move_on_after(0.01, with_value: :moved_on) do
|
|
41
43
|
sleep 0.007
|
|
@@ -71,7 +73,7 @@ class TimerCancelAfterTest < MiniTest::Test
|
|
|
71
73
|
end
|
|
72
74
|
end
|
|
73
75
|
t1 = Time.now
|
|
74
|
-
assert_in_range 0.01..0.03, t1 - t0
|
|
76
|
+
assert_in_range 0.01..0.03, t1 - t0 if IS_LINUX
|
|
75
77
|
end
|
|
76
78
|
|
|
77
79
|
def test_timer_cancel_after_with_reset
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: polyphony
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: '0.
|
|
4
|
+
version: '0.67'
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sharon Rosner
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2021-
|
|
11
|
+
date: 2021-08-06 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rake-compiler
|
|
@@ -156,6 +156,7 @@ files:
|
|
|
156
156
|
- README.md
|
|
157
157
|
- Rakefile
|
|
158
158
|
- TODO.md
|
|
159
|
+
- bin/pdbg
|
|
159
160
|
- bin/polyphony-debug
|
|
160
161
|
- bin/stress.rb
|
|
161
162
|
- bin/test
|
|
@@ -356,6 +357,7 @@ files:
|
|
|
356
357
|
- lib/polyphony/core/thread_pool.rb
|
|
357
358
|
- lib/polyphony/core/throttler.rb
|
|
358
359
|
- lib/polyphony/core/timer.rb
|
|
360
|
+
- lib/polyphony/debugger/server.rb
|
|
359
361
|
- lib/polyphony/extensions/core.rb
|
|
360
362
|
- lib/polyphony/extensions/debug.rb
|
|
361
363
|
- lib/polyphony/extensions/fiber.rb
|