polyphony 0.43.8

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.
Files changed (221) hide show
  1. checksums.yaml +7 -0
  2. data/.gitbook.yaml +4 -0
  3. data/.github/workflows/test.yml +29 -0
  4. data/.gitignore +59 -0
  5. data/.rubocop.yml +175 -0
  6. data/CHANGELOG.md +393 -0
  7. data/Gemfile +3 -0
  8. data/Gemfile.lock +141 -0
  9. data/LICENSE +21 -0
  10. data/README.md +51 -0
  11. data/Rakefile +26 -0
  12. data/TODO.md +201 -0
  13. data/bin/polyphony-debug +87 -0
  14. data/docs/_config.yml +64 -0
  15. data/docs/_includes/head.html +40 -0
  16. data/docs/_includes/title.html +1 -0
  17. data/docs/_sass/custom/custom.scss +10 -0
  18. data/docs/_sass/overrides.scss +0 -0
  19. data/docs/_user-guide/all-about-timers.md +126 -0
  20. data/docs/_user-guide/index.md +9 -0
  21. data/docs/_user-guide/web-server.md +136 -0
  22. data/docs/api-reference/exception.md +27 -0
  23. data/docs/api-reference/fiber.md +425 -0
  24. data/docs/api-reference/index.md +9 -0
  25. data/docs/api-reference/io.md +36 -0
  26. data/docs/api-reference/object.md +99 -0
  27. data/docs/api-reference/polyphony-baseexception.md +33 -0
  28. data/docs/api-reference/polyphony-cancel.md +26 -0
  29. data/docs/api-reference/polyphony-moveon.md +24 -0
  30. data/docs/api-reference/polyphony-net.md +20 -0
  31. data/docs/api-reference/polyphony-process.md +28 -0
  32. data/docs/api-reference/polyphony-resourcepool.md +59 -0
  33. data/docs/api-reference/polyphony-restart.md +18 -0
  34. data/docs/api-reference/polyphony-terminate.md +18 -0
  35. data/docs/api-reference/polyphony-threadpool.md +67 -0
  36. data/docs/api-reference/polyphony-throttler.md +77 -0
  37. data/docs/api-reference/polyphony.md +36 -0
  38. data/docs/api-reference/thread.md +88 -0
  39. data/docs/assets/img/echo-fibers.svg +1 -0
  40. data/docs/assets/img/sleeping-fiber.svg +1 -0
  41. data/docs/faq.md +195 -0
  42. data/docs/favicon.ico +0 -0
  43. data/docs/getting-started/index.md +10 -0
  44. data/docs/getting-started/installing.md +34 -0
  45. data/docs/getting-started/overview.md +486 -0
  46. data/docs/getting-started/tutorial.md +359 -0
  47. data/docs/index.md +94 -0
  48. data/docs/main-concepts/concurrency.md +151 -0
  49. data/docs/main-concepts/design-principles.md +161 -0
  50. data/docs/main-concepts/exception-handling.md +291 -0
  51. data/docs/main-concepts/extending.md +89 -0
  52. data/docs/main-concepts/fiber-scheduling.md +197 -0
  53. data/docs/main-concepts/index.md +9 -0
  54. data/docs/polyphony-logo.png +0 -0
  55. data/examples/adapters/concurrent-ruby.rb +9 -0
  56. data/examples/adapters/pg_client.rb +36 -0
  57. data/examples/adapters/pg_notify.rb +35 -0
  58. data/examples/adapters/pg_pool.rb +43 -0
  59. data/examples/adapters/pg_transaction.rb +31 -0
  60. data/examples/adapters/redis_blpop.rb +12 -0
  61. data/examples/adapters/redis_channels.rb +122 -0
  62. data/examples/adapters/redis_client.rb +19 -0
  63. data/examples/adapters/redis_pubsub.rb +26 -0
  64. data/examples/adapters/redis_pubsub_perf.rb +68 -0
  65. data/examples/core/01-spinning-up-fibers.rb +18 -0
  66. data/examples/core/02-awaiting-fibers.rb +20 -0
  67. data/examples/core/03-interrupting.rb +39 -0
  68. data/examples/core/04-handling-signals.rb +19 -0
  69. data/examples/core/xx-agent.rb +102 -0
  70. data/examples/core/xx-at_exit.rb +29 -0
  71. data/examples/core/xx-caller.rb +12 -0
  72. data/examples/core/xx-channels.rb +45 -0
  73. data/examples/core/xx-daemon.rb +14 -0
  74. data/examples/core/xx-deadlock.rb +8 -0
  75. data/examples/core/xx-deferring-an-operation.rb +14 -0
  76. data/examples/core/xx-erlang-style-genserver.rb +81 -0
  77. data/examples/core/xx-exception-backtrace.rb +40 -0
  78. data/examples/core/xx-fork-cleanup.rb +22 -0
  79. data/examples/core/xx-fork-spin.rb +42 -0
  80. data/examples/core/xx-fork-terminate.rb +27 -0
  81. data/examples/core/xx-forking.rb +24 -0
  82. data/examples/core/xx-move_on.rb +23 -0
  83. data/examples/core/xx-pingpong.rb +18 -0
  84. data/examples/core/xx-queue-async.rb +120 -0
  85. data/examples/core/xx-readpartial.rb +18 -0
  86. data/examples/core/xx-recurrent-timer.rb +12 -0
  87. data/examples/core/xx-resource_delegate.rb +31 -0
  88. data/examples/core/xx-signals.rb +16 -0
  89. data/examples/core/xx-sleep-forever.rb +9 -0
  90. data/examples/core/xx-sleeping.rb +25 -0
  91. data/examples/core/xx-snooze-starve.rb +16 -0
  92. data/examples/core/xx-spin-fork.rb +49 -0
  93. data/examples/core/xx-spin_error_backtrace.rb +33 -0
  94. data/examples/core/xx-state-machine.rb +51 -0
  95. data/examples/core/xx-stop.rb +20 -0
  96. data/examples/core/xx-supervise-process.rb +30 -0
  97. data/examples/core/xx-supervisors.rb +21 -0
  98. data/examples/core/xx-thread-selector-sleep.rb +51 -0
  99. data/examples/core/xx-thread-selector-snooze.rb +46 -0
  100. data/examples/core/xx-thread-sleep.rb +17 -0
  101. data/examples/core/xx-thread-snooze.rb +34 -0
  102. data/examples/core/xx-thread_pool.rb +17 -0
  103. data/examples/core/xx-throttling.rb +18 -0
  104. data/examples/core/xx-timeout.rb +10 -0
  105. data/examples/core/xx-timer-gc.rb +17 -0
  106. data/examples/core/xx-trace.rb +79 -0
  107. data/examples/core/xx-using-a-mutex.rb +21 -0
  108. data/examples/core/xx-worker-thread.rb +30 -0
  109. data/examples/io/tunnel.rb +48 -0
  110. data/examples/io/xx-backticks.rb +11 -0
  111. data/examples/io/xx-echo_client.rb +25 -0
  112. data/examples/io/xx-echo_client_from_stdin.rb +21 -0
  113. data/examples/io/xx-echo_pipe.rb +16 -0
  114. data/examples/io/xx-echo_server.rb +17 -0
  115. data/examples/io/xx-echo_server_with_timeout.rb +34 -0
  116. data/examples/io/xx-echo_stdin.rb +14 -0
  117. data/examples/io/xx-happy-eyeballs.rb +36 -0
  118. data/examples/io/xx-httparty.rb +38 -0
  119. data/examples/io/xx-irb.rb +17 -0
  120. data/examples/io/xx-net-http.rb +15 -0
  121. data/examples/io/xx-open.rb +16 -0
  122. data/examples/io/xx-switch.rb +15 -0
  123. data/examples/io/xx-system.rb +11 -0
  124. data/examples/io/xx-tcpserver.rb +15 -0
  125. data/examples/io/xx-tcpsocket.rb +18 -0
  126. data/examples/io/xx-zip.rb +19 -0
  127. data/examples/performance/fiber_transfer.rb +47 -0
  128. data/examples/performance/fs_read.rb +38 -0
  129. data/examples/performance/mem-usage.rb +56 -0
  130. data/examples/performance/messaging.rb +29 -0
  131. data/examples/performance/multi_snooze.rb +33 -0
  132. data/examples/performance/snooze.rb +39 -0
  133. data/examples/performance/snooze_raw.rb +39 -0
  134. data/examples/performance/thread-vs-fiber/polyphony_mt_server.rb +74 -0
  135. data/examples/performance/thread-vs-fiber/polyphony_server.rb +45 -0
  136. data/examples/performance/thread-vs-fiber/polyphony_server_read_loop.rb +58 -0
  137. data/examples/performance/thread-vs-fiber/threaded_server.rb +27 -0
  138. data/examples/performance/thread-vs-fiber/xx-httparty_multi.rb +36 -0
  139. data/examples/performance/thread-vs-fiber/xx-httparty_threaded.rb +29 -0
  140. data/examples/performance/thread_pool_perf.rb +63 -0
  141. data/examples/performance/xx-array.rb +11 -0
  142. data/examples/performance/xx-fiber-switch.rb +9 -0
  143. data/examples/performance/xx-snooze.rb +15 -0
  144. data/examples/xx-spin.rb +32 -0
  145. data/ext/libev/Changes +548 -0
  146. data/ext/libev/LICENSE +37 -0
  147. data/ext/libev/README +59 -0
  148. data/ext/libev/README.embed +3 -0
  149. data/ext/libev/ev.c +5279 -0
  150. data/ext/libev/ev.h +856 -0
  151. data/ext/libev/ev_epoll.c +296 -0
  152. data/ext/libev/ev_kqueue.c +224 -0
  153. data/ext/libev/ev_linuxaio.c +642 -0
  154. data/ext/libev/ev_poll.c +156 -0
  155. data/ext/libev/ev_port.c +192 -0
  156. data/ext/libev/ev_select.c +316 -0
  157. data/ext/libev/ev_vars.h +215 -0
  158. data/ext/libev/ev_win32.c +162 -0
  159. data/ext/libev/ev_wrap.h +216 -0
  160. data/ext/libev/test_libev_win32.c +123 -0
  161. data/ext/polyphony/extconf.rb +20 -0
  162. data/ext/polyphony/fiber.c +109 -0
  163. data/ext/polyphony/libev.c +2 -0
  164. data/ext/polyphony/libev.h +9 -0
  165. data/ext/polyphony/libev_agent.c +882 -0
  166. data/ext/polyphony/polyphony.c +71 -0
  167. data/ext/polyphony/polyphony.h +97 -0
  168. data/ext/polyphony/polyphony_ext.c +21 -0
  169. data/ext/polyphony/queue.c +168 -0
  170. data/ext/polyphony/ring_buffer.c +96 -0
  171. data/ext/polyphony/ring_buffer.h +28 -0
  172. data/ext/polyphony/thread.c +208 -0
  173. data/ext/polyphony/tracing.c +11 -0
  174. data/lib/polyphony.rb +136 -0
  175. data/lib/polyphony/adapters/fs.rb +19 -0
  176. data/lib/polyphony/adapters/irb.rb +52 -0
  177. data/lib/polyphony/adapters/postgres.rb +110 -0
  178. data/lib/polyphony/adapters/process.rb +33 -0
  179. data/lib/polyphony/adapters/redis.rb +67 -0
  180. data/lib/polyphony/adapters/trace.rb +138 -0
  181. data/lib/polyphony/core/channel.rb +46 -0
  182. data/lib/polyphony/core/exceptions.rb +36 -0
  183. data/lib/polyphony/core/global_api.rb +124 -0
  184. data/lib/polyphony/core/resource_pool.rb +117 -0
  185. data/lib/polyphony/core/sync.rb +21 -0
  186. data/lib/polyphony/core/thread_pool.rb +64 -0
  187. data/lib/polyphony/core/throttler.rb +41 -0
  188. data/lib/polyphony/event.rb +17 -0
  189. data/lib/polyphony/extensions/core.rb +174 -0
  190. data/lib/polyphony/extensions/fiber.rb +379 -0
  191. data/lib/polyphony/extensions/io.rb +221 -0
  192. data/lib/polyphony/extensions/openssl.rb +81 -0
  193. data/lib/polyphony/extensions/socket.rb +150 -0
  194. data/lib/polyphony/extensions/thread.rb +108 -0
  195. data/lib/polyphony/net.rb +77 -0
  196. data/lib/polyphony/version.rb +5 -0
  197. data/polyphony.gemspec +40 -0
  198. data/test/coverage.rb +54 -0
  199. data/test/eg.rb +27 -0
  200. data/test/helper.rb +56 -0
  201. data/test/q.rb +24 -0
  202. data/test/run.rb +5 -0
  203. data/test/stress.rb +25 -0
  204. data/test/test_agent.rb +130 -0
  205. data/test/test_event.rb +59 -0
  206. data/test/test_ext.rb +196 -0
  207. data/test/test_fiber.rb +988 -0
  208. data/test/test_global_api.rb +352 -0
  209. data/test/test_io.rb +249 -0
  210. data/test/test_kernel.rb +57 -0
  211. data/test/test_process_supervision.rb +46 -0
  212. data/test/test_queue.rb +112 -0
  213. data/test/test_resource_pool.rb +138 -0
  214. data/test/test_signal.rb +100 -0
  215. data/test/test_socket.rb +34 -0
  216. data/test/test_supervise.rb +103 -0
  217. data/test/test_thread.rb +170 -0
  218. data/test/test_thread_pool.rb +101 -0
  219. data/test/test_throttler.rb +50 -0
  220. data/test/test_trace.rb +68 -0
  221. metadata +482 -0
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ Exception.__disable_sanitized_backtrace__ = true
7
+
8
+ buffer = +''
9
+ socket = TCPSocket.new('google.com', 80)
10
+ socket.send("GET /?q=time HTTP/1.1\r\nHost: google.com\r\n\r\n", 0)
11
+ move_on_after(5) {
12
+ while (data = socket.readpartial(8192))
13
+ buffer << data
14
+ end
15
+ }
16
+
17
+ puts "*" * 40
18
+ p buffer
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ move_on_after(3) do
7
+ puts 'Start...'
8
+ every(1) do
9
+ puts Time.now
10
+ end
11
+ end
12
+ puts 'done!'
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ class Number
7
+ def initialize(id)
8
+ @id = id
9
+ end
10
+
11
+ def greet(other)
12
+ puts "You are number #{other}, I am number #{@id}"
13
+ sleep(0.05 + rand * 0.2)
14
+ end
15
+ end
16
+
17
+ resource_count = 0
18
+ Pool = Polyphony::ResourcePool.new(limit: 3) do
19
+ Number.new(resource_count += 1)
20
+ end
21
+
22
+ def meet(number)
23
+ loop do
24
+ Pool.greet(number)
25
+ end
26
+ end
27
+
28
+ 3.times { |x| spin { meet(x) } }
29
+
30
+ t0 = Time.now
31
+ every(10) { puts "uptime: #{Time.now - t0}" }
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ waiter = spin do
7
+ puts 'Waiting for HUP'
8
+ Polyphony.wait_for_signal('SIGHUP')
9
+ puts 'Got HUP'
10
+ end
11
+
12
+ sleep 1
13
+ puts 'Sending HUP'
14
+ Process.kill('SIGHUP', Process.pid)
15
+
16
+ suspend
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ Exception.__disable_sanitized_backtrace__ = true
7
+
8
+ puts "press Ctrl-C!"
9
+ sleep
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ Exception.__disable_sanitized_backtrace__ = true
7
+
8
+ # spin {
9
+ # 10.times {
10
+ # STDOUT << '.'
11
+ # sleep 0.1
12
+ # }
13
+ # }
14
+
15
+ puts 'going to sleep...'
16
+ sleep 1
17
+ puts 'woke up'
18
+
19
+ counter = 0
20
+ t = Polyphony::Throttler.new(5)
21
+ t.process do
22
+ p counter
23
+ counter += 1
24
+ t.stop if counter > 5
25
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ Exception.__disable_sanitized_backtrace__ = true
7
+
8
+ f = spin_loop {
9
+ snooze
10
+ }
11
+
12
+ puts 'going to sleep...'
13
+ sleep 1
14
+ puts 'woke up'
15
+ f.stop
16
+
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ Exception.__disable_sanitized_backtrace__ = true
7
+
8
+ puts "Parent pid: #{Process.pid}"
9
+
10
+ def start_worker
11
+ Polyphony.fork do
12
+ p :sleep
13
+ sleep 5
14
+ p :done_sleeping
15
+ ensure
16
+ p :start_worker_fork_ensure
17
+ end
18
+ end
19
+
20
+ f = spin do
21
+ Polyphony::ProcessSupervisor.supervise do
22
+ spin do
23
+ spin do
24
+ p :sleep
25
+ sleep 5
26
+ p :done_sleeping
27
+ end.await
28
+ end.await
29
+ ensure
30
+ p :start_worker_fork_ensure
31
+ end
32
+ # spin do
33
+ # pid = start_worker
34
+ # p [:before_child_await, pid]
35
+ # Gyro::Child.new(pid).await
36
+ # p :after_child_await
37
+ # ensure
38
+ # puts "child done"
39
+ # end
40
+ # supervise
41
+ # ensure
42
+ # puts "kill child"
43
+ # Process.kill('TERM', pid) rescue nil
44
+ end
45
+
46
+ sleep 1
47
+ puts "terminate worker"
48
+ f.terminate
49
+ f.await
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ def error(t)
7
+ raise "hello #{t}"
8
+ end
9
+
10
+ def deferred_error(t)
11
+ puts "deferred_error"
12
+ spin { de2(t) }
13
+ end
14
+
15
+ def de2(t)
16
+ snooze
17
+ error(t)
18
+ end
19
+
20
+ def spin_with_error
21
+ spin { error(4) }
22
+ end
23
+
24
+ spin do
25
+ spin do
26
+ spin do
27
+ deferred_error(3)
28
+ end.await
29
+ end.await
30
+ end.await
31
+
32
+ suspend
33
+ suspend
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ # require 'bundler/setup'
4
+ # require 'polyphony'
5
+
6
+ require 'fiber'
7
+
8
+ class StateMachine < ::Fiber
9
+ def initialize(state, rules)
10
+ @state = state
11
+ @rules = rules
12
+ super() { |input| state_loop(input) }
13
+ end
14
+
15
+ attr_reader :state
16
+ def state_loop(input)
17
+ loop do
18
+ @state = apply(input)
19
+ input = Fiber.yield(@state)
20
+ end
21
+ end
22
+
23
+ def apply(input)
24
+ f = @rules[@state][input]
25
+ return f.(@state) if f.is_a?(Proc)
26
+
27
+ raise 'Invalid input'
28
+ rescue => e
29
+ @state
30
+ end
31
+
32
+ def transition(input)
33
+ state = self.resume(input)
34
+ # state.is_a?(Exception) ? (raise state) : state
35
+ end
36
+ end
37
+
38
+ o = StateMachine.new(
39
+ :off,
40
+ {
41
+ off: { turnon: ->(s) { :on } },
42
+ on: { turnoff: ->(s) { :off } }
43
+ }
44
+ )
45
+
46
+ loop do
47
+ STDOUT << "#{o.state}: "
48
+ input = gets.strip.to_sym
49
+ # puts " command: #{input.inspect}"
50
+ o.transition(input)
51
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ f1 = spin do
7
+ f2 = spin { sleep 60 }
8
+ f3 = spin { sleep 60 }
9
+ sleep 60
10
+ ensure
11
+ p 1
12
+ f2.stop
13
+ p 2
14
+ f3.stop
15
+ p "should reach here!"
16
+ end
17
+
18
+ sleep 0.1
19
+ f1.stop
20
+ snooze
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ Exception.__disable_sanitized_backtrace__ = true
7
+
8
+ supervisor = spin do
9
+ puts "parent pid #{Process.pid}"
10
+
11
+ Polyphony::ProcessSupervisor.supervise do
12
+ puts "child pid #{Process.pid}"
13
+ puts "go to sleep"
14
+ sleep 5
15
+ rescue Interrupt
16
+ puts "child got INT"
17
+ rescue SystemExit
18
+ puts "child got TERM"
19
+ ensure
20
+ puts "done sleeping"
21
+ end
22
+ end
23
+
24
+ begin
25
+ supervisor.await
26
+ rescue Interrupt
27
+ exit!
28
+ # supervisor.terminate
29
+ # supervisor.await
30
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ def my_sleep(t)
7
+ puts "#{t} start"
8
+ sleep(t)
9
+ puts "#{t} done"
10
+ end
11
+
12
+ puts "#{Time.now} waiting..."
13
+ supervise do |s|
14
+ s.spin { my_sleep(1) }
15
+ s.spin { my_sleep(2) }
16
+ s.spin { my_sleep(3) }
17
+ s.spin do
18
+ puts "fiber count: #{Fiber.count}"
19
+ end
20
+ end
21
+ puts "#{Time.now} done waiting"
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ # Thread.event_selector = Gyro::Selector
7
+ # Thread.current.setup_fiber_scheduling
8
+
9
+ t = Gyro::Timer.new(1, 1)
10
+ s = spin {
11
+ last = Time.now
12
+ loop do
13
+ t.await
14
+ now = Time.now
15
+ puts "elapsed: #{now - last}"
16
+ last = now
17
+ end
18
+ }
19
+ s.await
20
+ exit!
21
+
22
+ p :go_to_sleep
23
+ sleep 1
24
+ p :wake_up
25
+
26
+ puts "*" * 60
27
+
28
+ t = Thread.new {
29
+ Thread.current.setup_fiber_scheduling
30
+
31
+ spin {
32
+ p :go_to_sleep1
33
+ sleep 1
34
+ p :wake_up1
35
+ }
36
+
37
+ spin {
38
+ p :go_to_sleep2
39
+ sleep 2
40
+ p :wake_up2
41
+ }
42
+
43
+ p :waiting
44
+ suspend
45
+ }
46
+
47
+ t.join
48
+
49
+ at_exit {
50
+ p :at_exit
51
+ }
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ Exception.__disable_sanitized_backtrace__ = true
7
+ Thread.event_selector = Gyro::Selector
8
+ Thread.current.setup_fiber_scheduling
9
+
10
+ def bm(fibers, iterations)
11
+ count = {}
12
+
13
+ t0 = Time.now
14
+ threads = (1..1).map do |i|
15
+ Thread.new do
16
+ count[i] = 0
17
+ supervise do |s|
18
+ fibers.times do
19
+ s.spin do
20
+ iterations.times do
21
+ snooze
22
+ count[i] += 1
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ threads.each(&:join)
30
+ dt = Time.now - t0
31
+ count = count.values.inject(0, &:+)
32
+ puts "#{[fibers, iterations].inspect} count: #{count} #{count / dt.to_f}/s"
33
+ end
34
+
35
+ # GC.disable
36
+
37
+ loop {
38
+ puts "*" * 60
39
+ bm(1, 1_000_000)
40
+ bm(10, 100_000)
41
+ bm(100, 10_000)
42
+ bm(1_000, 1_000)
43
+ bm(10_000, 100)
44
+ bm(100_000, 10)
45
+ # bm(1_000_000, 1)
46
+ }