polyphony 0.55.0 → 0.59.1

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.
@@ -3,8 +3,8 @@
3
3
  module Polyphony
4
4
  # Implements a common timer for running multiple timeouts
5
5
  class Timer
6
- def initialize(resolution:)
7
- @fiber = spin_loop(interval: resolution) { update }
6
+ def initialize(tag = nil, resolution:)
7
+ @fiber = spin_loop(tag, interval: resolution) { update }
8
8
  @timeouts = {}
9
9
  end
10
10
 
@@ -262,7 +262,7 @@ module Polyphony
262
262
  @parent = parent
263
263
  @caller = caller
264
264
  @block = block
265
- __fiber_trace__(:fiber_create, self)
265
+ Thread.backend.trace(:fiber_create, self)
266
266
  schedule
267
267
  end
268
268
 
@@ -311,7 +311,7 @@ module Polyphony
311
311
 
312
312
  def finalize(result, uncaught_exception = false)
313
313
  result, uncaught_exception = finalize_children(result, uncaught_exception)
314
- __fiber_trace__(:fiber_terminate, self, result)
314
+ Thread.backend.trace(:fiber_terminate, self, result)
315
315
  @result = result
316
316
  @running = false
317
317
  inform_dependants(result, uncaught_exception)
@@ -105,4 +105,12 @@ class ::Thread
105
105
  main_fiber << value
106
106
  end
107
107
  alias_method :send, :<<
108
+
109
+ def idle_gc_period=(period)
110
+ backend.idle_gc_period = period
111
+ end
112
+
113
+ def on_idle(&block)
114
+ backend.idle_proc = block
115
+ end
108
116
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Polyphony
4
- VERSION = '0.55.0'
4
+ VERSION = '0.59.1'
5
5
  end
data/test/test_backend.rb CHANGED
@@ -281,6 +281,97 @@ class BackendTest < MiniTest::Test
281
281
  f.await
282
282
  end
283
283
  end
284
+
285
+
286
+ def test_splice_chunks
287
+ body = 'abcd' * 250
288
+ chunk_size = 750
289
+
290
+ buf = +''
291
+ r, w = IO.pipe
292
+ reader = spin do
293
+ r.read_loop { |data| buf << data }
294
+ end
295
+
296
+ i, o = IO.pipe
297
+ writer = spin do
298
+ o << body
299
+ o.close
300
+ end
301
+ Thread.current.backend.splice_chunks(
302
+ i,
303
+ w,
304
+ "Content-Type: foo\r\n\r\n",
305
+ "0\r\n\r\n",
306
+ ->(len) { "#{len.to_s(16)}\r\n" },
307
+ "\r\n",
308
+ chunk_size
309
+ )
310
+ w.close
311
+ reader.await
312
+
313
+ expected = "Content-Type: foo\r\n\r\n#{750.to_s(16)}\r\n#{body[0..749]}\r\n#{250.to_s(16)}\r\n#{body[750..999]}\r\n0\r\n\r\n"
314
+ assert_equal expected, buf
315
+ ensure
316
+ o.close
317
+ w.close
318
+ end
319
+
320
+ def test_idle_gc
321
+ GC.disable
322
+
323
+ count = GC.count
324
+ snooze
325
+ assert_equal count, GC.count
326
+ sleep 0.01
327
+ assert_equal count, GC.count
328
+
329
+ @backend.idle_gc_period = 0.1
330
+ snooze
331
+ assert_equal count, GC.count
332
+ sleep 0.05
333
+ assert_equal count, GC.count
334
+ # The idle tasks are ran at most once per fiber switch, before the backend
335
+ # is polled. Therefore, the second sleep will not have triggered a GC, since
336
+ # only 0.05s have passed since the gc period was set.
337
+ sleep 0.07
338
+ assert_equal count, GC.count
339
+ # Upon the third sleep the GC should be triggered, at 0.12s post setting the
340
+ # GC period.
341
+ sleep 0.05
342
+ assert_equal count + 1, GC.count
343
+
344
+ @backend.idle_gc_period = 0
345
+ count = GC.count
346
+ sleep 0.001
347
+ sleep 0.002
348
+ sleep 0.003
349
+ assert_equal count, GC.count
350
+ ensure
351
+ GC.enable
352
+ end
353
+
354
+ def test_idle_proc
355
+ counter = 0
356
+
357
+ @backend.idle_proc = proc { counter += 1 }
358
+
359
+ 3.times { snooze }
360
+ assert_equal 0, counter
361
+
362
+ sleep 0.01
363
+ assert_equal 1, counter
364
+ sleep 0.01
365
+ assert_equal 2, counter
366
+
367
+ assert_equal 2, counter
368
+ 3.times { snooze }
369
+ assert_equal 2, counter
370
+
371
+ @backend.idle_proc = nil
372
+ sleep 0.01
373
+ assert_equal 2, counter
374
+ end
284
375
  end
285
376
 
286
377
  class BackendChainTest < MiniTest::Test
data/test/test_thread.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'helper'
4
- require 'polyphony/adapters/trace'
5
4
 
6
5
  class ThreadTest < MiniTest::Test
7
6
  def test_thread_spin
@@ -130,18 +129,13 @@ class ThreadTest < MiniTest::Test
130
129
 
131
130
  def test_that_suspend_returns_immediately_if_no_watchers
132
131
  records = []
133
- t = Polyphony::Trace.new(:fiber_all) do |r|
134
- records << r if r[:event] =~ /^fiber_/
135
- end
136
- t.enable
137
- Polyphony.trace(true)
138
-
132
+ Thread.backend.trace_proc = proc {|*r| records << r }
139
133
  suspend
140
- t.disable
141
- assert_equal [:fiber_switchpoint], records.map { |r| r[:event] }
134
+ assert_equal [
135
+ [:fiber_switchpoint, Fiber.current]
136
+ ], records
142
137
  ensure
143
- t&.disable
144
- Polyphony.trace(false)
138
+ Thread.backend.trace_proc = nil
145
139
  end
146
140
 
147
141
  def test_thread_child_fiber_termination
@@ -171,4 +165,56 @@ class ThreadTest < MiniTest::Test
171
165
  t&.kill
172
166
  t&.join
173
167
  end
168
+
169
+ def test_idle_gc
170
+ GC.disable
171
+
172
+ count = GC.count
173
+ snooze
174
+ assert_equal count, GC.count
175
+ sleep 0.01
176
+ assert_equal count, GC.count
177
+
178
+ Thread.current.idle_gc_period = 0.1
179
+ snooze
180
+ assert_equal count, GC.count
181
+ sleep 0.05
182
+ assert_equal count, GC.count
183
+ # The idle tasks are ran at most once per fiber switch, before the backend
184
+ # is polled. Therefore, the second sleep will not have triggered a GC, since
185
+ # only 0.05s have passed since the gc period was set.
186
+ sleep 0.07
187
+ assert_equal count, GC.count
188
+ # Upon the third sleep the GC should be triggered, at 0.12s post setting the
189
+ # GC period.
190
+ sleep 0.05
191
+ assert_equal count + 1, GC.count
192
+
193
+ Thread.current.idle_gc_period = 0
194
+ count = GC.count
195
+ sleep 0.001
196
+ sleep 0.002
197
+ sleep 0.003
198
+ assert_equal count, GC.count
199
+ ensure
200
+ GC.enable
201
+ end
202
+
203
+ def test_on_idle
204
+ counter = 0
205
+
206
+ Thread.current.on_idle { counter += 1 }
207
+
208
+ 3.times { snooze }
209
+ assert_equal 0, counter
210
+
211
+ sleep 0.01
212
+ assert_equal 1, counter
213
+ sleep 0.01
214
+ assert_equal 2, counter
215
+
216
+ assert_equal 2, counter
217
+ 3.times { snooze }
218
+ assert_equal 2, counter
219
+ end
174
220
  end
data/test/test_timer.rb CHANGED
@@ -48,7 +48,7 @@ class TimerMoveOnAfterTest < MiniTest::Test
48
48
  t1 = Time.now
49
49
 
50
50
  assert_nil v
51
- assert_in_range 0.015..0.03, t1 - t0
51
+ assert_in_range 0.015..0.04, t1 - t0
52
52
  end
53
53
  end
54
54
 
@@ -76,17 +76,17 @@ class TimerCancelAfterTest < MiniTest::Test
76
76
 
77
77
  def test_timer_cancel_after_with_reset
78
78
  buf = []
79
- @timer.cancel_after(0.01) do
80
- sleep 0.005
79
+ @timer.cancel_after(0.13) do
80
+ sleep 0.05
81
81
  buf << 1
82
82
  @timer.reset
83
- sleep 0.005
83
+ sleep 0.05
84
84
  buf << 2
85
85
  @timer.reset
86
- sleep 0.005
86
+ sleep 0.05
87
87
  buf << 3
88
88
  @timer.reset
89
- sleep 0.005
89
+ sleep 0.05
90
90
  buf << 4
91
91
  end
92
92
  assert_equal [1, 2, 3, 4], buf
@@ -158,6 +158,6 @@ class TimerMiscTest < MiniTest::Test
158
158
  end
159
159
  sleep 0.05
160
160
  f.stop
161
- assert_in_range 4..6, buffer.size
161
+ assert_in_range 3..7, buffer.size
162
162
  end
163
163
  end
data/test/test_trace.rb CHANGED
@@ -1,70 +1,48 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'helper'
4
- require 'polyphony/adapters/trace'
5
4
 
6
5
  class TraceTest < MiniTest::Test
7
- def test_tracing_disabled
8
- records = []
9
- t = Polyphony::Trace.new { |r| records << r if r[:event] =~ /^fiber_/ }
10
- t.enable
11
- snooze
12
- assert_equal 0, records.size
13
- ensure
14
- t&.disable
15
- Polyphony.trace(nil)
16
- end
17
-
18
6
  def test_tracing_enabled
19
- records = []
20
- t = Polyphony::Trace.new(:fiber_all) { |r| records << r if r[:event] =~ /^fiber_/ }
21
- Polyphony.trace(true)
22
- t.enable
7
+ events = []
8
+ Thread.backend.trace_proc = proc { |*e| events << e }
23
9
  snooze
24
- t.disable
25
10
 
26
- assert_equal 3, records.size
27
- events = records.map { |r| r[:event] }
28
- assert_equal [:fiber_schedule, :fiber_switchpoint, :fiber_run], events
29
- assert_equal [Fiber.current], records.map { |r| r[:fiber] }.uniq
11
+ assert_equal [
12
+ [:fiber_schedule, Fiber.current, nil],
13
+ [:fiber_switchpoint, Fiber.current],
14
+ [:fiber_run, Fiber.current, nil]
15
+ ], events
30
16
  ensure
31
- t&.disable
32
- Polyphony.trace(nil)
17
+ Thread.backend.trace_proc = nil
33
18
  end
34
19
 
35
20
  def test_2_fiber_trace
36
- records = []
37
- thread = Thread.current
38
- t = Polyphony::Trace.new(:fiber_all) do |r|
39
- records << r if Thread.current == thread && r[:event] =~ /^fiber_/
40
- end
41
- t.enable
42
- Polyphony.trace(true)
21
+ events = []
22
+ Thread.backend.trace_proc = proc { |*e| events << e }
43
23
 
44
- f = spin { sleep 0 }
24
+ f = spin { sleep 0; :byebye }
45
25
  suspend
46
26
  sleep 0
47
27
 
48
- events = records.map { |r| [r[:fiber] == f ? :f : :current, r[:event]] }
49
28
  assert_equal [
50
- [:f, :fiber_create],
51
- [:f, :fiber_schedule],
52
- [:current, :fiber_switchpoint],
53
- [:f, :fiber_run],
54
- [:f, :fiber_switchpoint],
55
- [:f, :fiber_event_poll_enter],
56
- [:f, :fiber_schedule],
57
- [:f, :fiber_event_poll_leave],
58
- [:f, :fiber_run],
59
- [:f, :fiber_terminate],
60
- [:current, :fiber_switchpoint],
61
- [:current, :fiber_event_poll_enter],
62
- [:current, :fiber_schedule],
63
- [:current, :fiber_event_poll_leave],
64
- [:current, :fiber_run]
29
+ [:fiber_create, f],
30
+ [:fiber_schedule, f, nil],
31
+ [:fiber_switchpoint, Fiber.current],
32
+ [:fiber_run, f, nil],
33
+ [:fiber_switchpoint, f],
34
+ [:fiber_event_poll_enter, f],
35
+ [:fiber_schedule, f, nil],
36
+ [:fiber_event_poll_leave, f],
37
+ [:fiber_run, f, nil],
38
+ [:fiber_terminate, f, :byebye],
39
+ [:fiber_switchpoint, Fiber.current],
40
+ [:fiber_event_poll_enter, Fiber.current],
41
+ [:fiber_schedule, Fiber.current, nil],
42
+ [:fiber_event_poll_leave, Fiber.current],
43
+ [:fiber_run, Fiber.current, nil]
65
44
  ], events
66
45
  ensure
67
- t&.disable
68
- Polyphony.trace(nil)
46
+ Thread.backend.trace_proc = nil
69
47
  end
70
48
  end
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.55.0
4
+ version: 0.59.1
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-06-17 00:00:00.000000000 Z
11
+ date: 2021-06-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -324,6 +324,7 @@ files:
324
324
  - examples/core/erlang-style-genserver.rb
325
325
  - examples/core/forking.rb
326
326
  - examples/core/handling-signals.rb
327
+ - examples/core/idle_gc.rb
327
328
  - examples/core/interrupt.rb
328
329
  - examples/core/nested.rb
329
330
  - examples/core/pingpong.rb
@@ -355,10 +356,12 @@ files:
355
356
  - examples/io/irb.rb
356
357
  - examples/io/net-http.rb
357
358
  - examples/io/open.rb
359
+ - examples/io/pipe.rb
358
360
  - examples/io/pry.rb
359
361
  - examples/io/rack_server.rb
360
362
  - examples/io/raw.rb
361
363
  - examples/io/reline.rb
364
+ - examples/io/splice_chunks.rb
362
365
  - examples/io/stdio.rb
363
366
  - examples/io/system.rb
364
367
  - examples/io/tcp_proxy.rb
@@ -414,6 +417,7 @@ files:
414
417
  - ext/liburing/setup.c
415
418
  - ext/liburing/syscall.c
416
419
  - ext/liburing/syscall.h
420
+ - ext/polyphony/backend_common.c
417
421
  - ext/polyphony/backend_common.h
418
422
  - ext/polyphony/backend_io_uring.c
419
423
  - ext/polyphony/backend_io_uring_context.c
@@ -433,11 +437,11 @@ files:
433
437
  - ext/polyphony/ring_buffer.c
434
438
  - ext/polyphony/ring_buffer.h
435
439
  - ext/polyphony/runqueue.c
440
+ - ext/polyphony/runqueue.h
436
441
  - ext/polyphony/runqueue_ring_buffer.c
437
442
  - ext/polyphony/runqueue_ring_buffer.h
438
443
  - ext/polyphony/socket_extensions.c
439
444
  - ext/polyphony/thread.c
440
- - ext/polyphony/tracing.c
441
445
  - lib/polyphony.rb
442
446
  - lib/polyphony/adapters/fs.rb
443
447
  - lib/polyphony/adapters/irb.rb
@@ -447,7 +451,6 @@ files:
447
451
  - lib/polyphony/adapters/readline.rb
448
452
  - lib/polyphony/adapters/redis.rb
449
453
  - lib/polyphony/adapters/sequel.rb
450
- - lib/polyphony/adapters/trace.rb
451
454
  - lib/polyphony/core/channel.rb
452
455
  - lib/polyphony/core/exceptions.rb
453
456
  - lib/polyphony/core/global_api.rb
@@ -1,11 +0,0 @@
1
- #include "polyphony.h"
2
-
3
- int __tracing_enabled__ = 0;
4
-
5
- VALUE __fiber_trace__(int argc, VALUE *argv, VALUE self) {
6
- return rb_ary_new4(argc, argv);
7
- }
8
-
9
- void Init_Tracing() {
10
- rb_define_global_function("__fiber_trace__", __fiber_trace__, -1);
11
- }