polyphony 0.16 → 0.17
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/CHANGELOG.md +11 -0
- data/Gemfile.lock +1 -1
- data/README.md +11 -11
- data/TODO.md +14 -5
- data/examples/core/channel_echo.rb +3 -3
- data/examples/core/enumerator.rb +1 -1
- data/examples/core/fork.rb +1 -1
- data/examples/core/genserver.rb +1 -1
- data/examples/core/lock.rb +3 -3
- data/examples/core/multiple_spawn.rb +2 -2
- data/examples/core/nested_async.rb +1 -1
- data/examples/core/nested_multiple_spawn.rb +3 -3
- data/examples/core/resource.rb +1 -1
- data/examples/core/resource_cancel.rb +1 -1
- data/examples/core/resource_delegate.rb +1 -1
- data/examples/core/sleep_spawn.rb +2 -2
- data/examples/core/spawn.rb +1 -1
- data/examples/core/spawn_cancel.rb +1 -1
- data/examples/core/spawn_error.rb +5 -5
- data/examples/core/supervisor.rb +4 -4
- data/examples/core/supervisor_with_cancel_scope.rb +3 -3
- data/examples/core/supervisor_with_error.rb +4 -4
- data/examples/core/supervisor_with_manual_move_on.rb +4 -4
- data/examples/core/thread.rb +2 -2
- data/examples/core/thread_cancel.rb +2 -2
- data/examples/core/thread_pool.rb +2 -2
- data/examples/core/throttle.rb +3 -3
- data/examples/fs/read.rb +1 -1
- data/examples/http/happy_eyeballs.rb +1 -1
- data/examples/http/http_client.rb +1 -1
- data/examples/http/http_server.rb +1 -1
- data/examples/http/http_server_throttled.rb +1 -1
- data/examples/http/http_ws_server.rb +2 -2
- data/examples/http/https_wss_server.rb +1 -1
- data/examples/interfaces/pg_client.rb +1 -1
- data/examples/interfaces/pg_pool.rb +1 -1
- data/examples/interfaces/redis_channels.rb +5 -5
- data/examples/interfaces/redis_pubsub.rb +2 -2
- data/examples/interfaces/redis_pubsub_perf.rb +3 -3
- data/examples/io/cat.rb +13 -0
- data/examples/io/echo_client.rb +2 -2
- data/examples/io/echo_server.rb +1 -1
- data/examples/io/echo_server_with_timeout.rb +1 -1
- data/examples/io/echo_stdin.rb +1 -1
- data/examples/io/io_read.rb +9 -0
- data/examples/io/system.rb +11 -0
- data/examples/performance/perf_multi_snooze.rb +2 -2
- data/examples/performance/perf_snooze.rb +2 -2
- data/examples/performance/thread-vs-fiber/polyphony_server.rb +2 -2
- data/ext/ev/io.c +53 -4
- data/lib/polyphony/core/coprocess.rb +1 -0
- data/lib/polyphony/core/supervisor.rb +1 -1
- data/lib/polyphony/extensions/io.rb +97 -17
- data/lib/polyphony/extensions/kernel.rb +47 -27
- data/lib/polyphony/http/server.rb +1 -1
- data/lib/polyphony/postgres.rb +0 -4
- data/lib/polyphony/version.rb +1 -1
- data/test/test_coprocess.rb +13 -13
- data/test/test_core.rb +12 -12
- data/test/test_io.rb +95 -3
- data/test/test_kernel.rb +26 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 16bd848555e9b517c4114a4324fe65d27ed08b2ac3f638a94c10070f99eb1915
|
4
|
+
data.tar.gz: 96dac9a4e8b5fe09f78ad6ffae157f048fdb499fca3c78028145bffdad45cfbd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 39dbff6723dfe0e2a9919080d170d16b545081e8f57e8010a7a84402b185c3a7b0dbcb3b11390c854fdeee90f967a8d055d8b4e6adb4c0d4344ac79f7d8a4f94
|
7
|
+
data.tar.gz: cb0a008a4234cab661e8a7e8ed6a70919093d210135c983704e201b043082a8e268ff2d8f11cf755aab64e1118c817ac3287d938282c62d39fe02dd66ef25d19
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
0.17 2019-05-24
|
2
|
+
---------------
|
3
|
+
|
4
|
+
* Implement IO#read_watcher, IO#write_watcher in C for better performance
|
5
|
+
* Implement nonblocking (yielding) versions of Kernel#system, IO.popen,
|
6
|
+
Process.detach, IO#gets IO#puts, other IO singleton methods
|
7
|
+
* Add Coprocess#join as alias to Coprocess#await
|
8
|
+
* Rename Kernel#spawn to Kernel#coproc
|
9
|
+
* Fix encoding of strings read with IO#read, IO#readpartial
|
10
|
+
* Fix non-blocking behaviour of IO#read, IO#readpartial, IO#write
|
11
|
+
|
1
12
|
0.16 2019-05-22
|
2
13
|
---------------
|
3
14
|
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Polyphony -
|
1
|
+
# Polyphony - lightweight concurrency for Ruby
|
2
2
|
|
3
3
|
[INSTALL](#installing-polyphony) |
|
4
4
|
[TUTORIAL](#getting-started) |
|
@@ -70,18 +70,18 @@ The reactor, in turn, may schedule other operations once they can be resumed. In
|
|
70
70
|
that manner, multiple ongoing operations may be processed concurrently.
|
71
71
|
|
72
72
|
There are multiple ways to start a concurrent operation, the most common of
|
73
|
-
which is `Kernel#
|
73
|
+
which is `Kernel#coproc`:
|
74
74
|
|
75
75
|
```ruby
|
76
76
|
require 'polyphony'
|
77
77
|
|
78
|
-
|
78
|
+
coproc do
|
79
79
|
puts "A going to sleep"
|
80
80
|
sleep 1
|
81
81
|
puts "A woken up"
|
82
82
|
end
|
83
83
|
|
84
|
-
|
84
|
+
coproc do
|
85
85
|
puts "B going to sleep"
|
86
86
|
sleep 1
|
87
87
|
puts "B woken up"
|
@@ -90,7 +90,7 @@ end
|
|
90
90
|
|
91
91
|
In the above example, both `sleep` calls will be executed concurrently, and thus
|
92
92
|
the program will take approximately only 1 second to execute. Note the lack of
|
93
|
-
any boilerplate relating to concurrency. Each `
|
93
|
+
any boilerplate relating to concurrency. Each `coproc` block starts a
|
94
94
|
*coprocess*, and is executed in sequential manner.
|
95
95
|
|
96
96
|
> **Coprocesses - the basic unit of concurrency**: In Polyphony, concurrent
|
@@ -115,8 +115,8 @@ require 'polyphony'
|
|
115
115
|
|
116
116
|
server = TCPServer.open(1234)
|
117
117
|
while client = server.accept
|
118
|
-
#
|
119
|
-
|
118
|
+
# coproc starts a new coprocess on a separate fiber
|
119
|
+
coproc {
|
120
120
|
while data = client.read rescue nil
|
121
121
|
client.write(data)
|
122
122
|
end
|
@@ -129,7 +129,7 @@ This example demonstrates several features of Polyphony:
|
|
129
129
|
- The code uses the native `TCPServer` class from Ruby's stdlib, to setup a TCP
|
130
130
|
server. The result of `server.accept` is also a native `TCPSocket` object.
|
131
131
|
There are no wrapper classes being used.
|
132
|
-
- The only hint of the code being concurrent is the use of `Kernel#
|
132
|
+
- The only hint of the code being concurrent is the use of `Kernel#coproc`,
|
133
133
|
which starts a new coprocess on a dedicated fiber. This allows serving
|
134
134
|
multiple clients at once. Whenever a blocking call is issued, such as
|
135
135
|
`#accept` or `#read`, execution is *yielded* to the event loop, which will
|
@@ -257,7 +257,7 @@ Pool = Polyphony::ResourcePool.new(limit: 5) {
|
|
257
257
|
}
|
258
258
|
|
259
259
|
1000.times {
|
260
|
-
|
260
|
+
coproc {
|
261
261
|
Pool.acquire { |db| p db.query('select 1') }
|
262
262
|
}
|
263
263
|
}
|
@@ -274,7 +274,7 @@ Pool = Polyphony::ResourcePool.new(limit: 5) {
|
|
274
274
|
}
|
275
275
|
|
276
276
|
1000.times {
|
277
|
-
|
277
|
+
coproc { p Pool.query('select 1') }
|
278
278
|
}
|
279
279
|
```
|
280
280
|
|
@@ -313,7 +313,7 @@ server = Net.tcp_listen(1234)
|
|
313
313
|
throttler = throttle(rate: 10) # up to 10 times per second
|
314
314
|
|
315
315
|
while client = server.accept
|
316
|
-
|
316
|
+
coproc {
|
317
317
|
throttler.call {
|
318
318
|
while data = client.read
|
319
319
|
client.write(data)
|
data/TODO.md
CHANGED
@@ -1,9 +1,13 @@
|
|
1
1
|
# Roadmap:
|
2
2
|
|
3
|
-
## 0.17
|
3
|
+
## 0.17 Implement non-blocking versions of `IO` API using monkey patching
|
4
4
|
|
5
|
-
-
|
6
|
-
-
|
5
|
+
- Don't worry about performance or completeness of behaviour
|
6
|
+
- Related global functions such as:
|
7
|
+
- `Kernel#system`
|
8
|
+
- `IO.popen`
|
9
|
+
- testing - check conformance to Ruby `IO` API (arguments and return values as
|
10
|
+
described in the Ruby docs)
|
7
11
|
|
8
12
|
## 0.18 Working net/http, httparty
|
9
13
|
|
@@ -20,14 +24,19 @@
|
|
20
24
|
|
21
25
|
## 0.20 Working Rails application
|
22
26
|
|
27
|
+
- app with database access (postgresql)
|
23
28
|
- benchmarks!
|
24
29
|
|
25
|
-
## 0.21
|
30
|
+
## 0.21 Support for multi-threading
|
31
|
+
|
32
|
+
- Separate event loop for each thread
|
33
|
+
|
34
|
+
## 0.22 Testing
|
26
35
|
|
27
36
|
- test thread / thread_pool modules
|
28
37
|
- report test coverage
|
29
38
|
|
30
|
-
## 0.
|
39
|
+
## 0.23 Documentation
|
31
40
|
|
32
41
|
# DNS
|
33
42
|
|
@@ -14,9 +14,9 @@ end
|
|
14
14
|
|
15
15
|
chan1, chan2 = Polyphony::Channel.new, Polyphony::Channel.new
|
16
16
|
|
17
|
-
echoer =
|
17
|
+
echoer = coproc { echo(chan1, chan2) }
|
18
18
|
|
19
|
-
|
19
|
+
coproc do
|
20
20
|
puts "start receiver"
|
21
21
|
while msg = chan2.receive
|
22
22
|
puts msg
|
@@ -26,7 +26,7 @@ ensure
|
|
26
26
|
puts "receiver stopped"
|
27
27
|
end
|
28
28
|
|
29
|
-
$main =
|
29
|
+
$main = coproc do
|
30
30
|
t0 = Time.now
|
31
31
|
puts "send hello"
|
32
32
|
chan1 << "hello"
|
data/examples/core/enumerator.rb
CHANGED
data/examples/core/fork.rb
CHANGED
data/examples/core/genserver.rb
CHANGED
data/examples/core/lock.rb
CHANGED
data/examples/core/resource.rb
CHANGED
data/examples/core/spawn.rb
CHANGED
@@ -9,11 +9,11 @@ def error(t)
|
|
9
9
|
raise "hello #{t}"
|
10
10
|
end
|
11
11
|
|
12
|
-
def
|
13
|
-
|
12
|
+
def coproc_with_error
|
13
|
+
coproc { error(2) }
|
14
14
|
end
|
15
15
|
|
16
|
-
|
16
|
+
coproc do
|
17
17
|
error(1)
|
18
18
|
rescue => e
|
19
19
|
e.cleanup_backtrace
|
@@ -23,6 +23,6 @@ rescue => e
|
|
23
23
|
puts
|
24
24
|
end
|
25
25
|
|
26
|
-
|
26
|
+
coproc_with_error
|
27
27
|
|
28
|
-
puts "done
|
28
|
+
puts "done coprocing"
|
data/examples/core/supervisor.rb
CHANGED
@@ -11,10 +11,10 @@ end
|
|
11
11
|
|
12
12
|
puts "#{Time.now} waiting..."
|
13
13
|
supervise do |s|
|
14
|
-
s.
|
15
|
-
s.
|
16
|
-
s.
|
17
|
-
s.
|
14
|
+
s.coproc my_sleep(1)
|
15
|
+
s.coproc my_sleep(2)
|
16
|
+
s.coproc my_sleep(3)
|
17
|
+
s.coproc {
|
18
18
|
puts "fiber count: #{Polyphony::FiberPool.size}"
|
19
19
|
}
|
20
20
|
end
|
@@ -14,9 +14,9 @@ puts "#{Time.now} going to sleep..."
|
|
14
14
|
move_on_after(0.5) do
|
15
15
|
supervise do |s|
|
16
16
|
puts "supervise block"
|
17
|
-
s.
|
18
|
-
s.
|
19
|
-
s.
|
17
|
+
s.coproc my_sleep(1)
|
18
|
+
s.coproc my_sleep(2)
|
19
|
+
s.coproc my_sleep(3)
|
20
20
|
end
|
21
21
|
puts "supervisor done"
|
22
22
|
end
|
@@ -8,12 +8,12 @@ async def my_sleep(t)
|
|
8
8
|
raise "blah"
|
9
9
|
end
|
10
10
|
|
11
|
-
|
11
|
+
coproc do
|
12
12
|
puts "#{Time.now} going to sleep..."
|
13
13
|
supervise do |s|
|
14
|
-
s.
|
15
|
-
s.
|
16
|
-
s.
|
14
|
+
s.coproc my_sleep(1)
|
15
|
+
s.coproc my_sleep(2)
|
16
|
+
s.coproc my_sleep(3)
|
17
17
|
end
|
18
18
|
rescue => e
|
19
19
|
puts "exception from supervisor: #{e}"
|
@@ -12,13 +12,13 @@ end
|
|
12
12
|
puts "#{Time.now} going to sleep..."
|
13
13
|
result = supervise do |s|
|
14
14
|
fiber = Fiber.current
|
15
|
-
|
15
|
+
coproc do
|
16
16
|
sleep(0.5)
|
17
17
|
puts "stopping supervisor..."
|
18
18
|
s.stop!
|
19
19
|
end
|
20
|
-
s.
|
21
|
-
s.
|
22
|
-
s.
|
20
|
+
s.coproc my_sleep(1)
|
21
|
+
s.coproc my_sleep(2)
|
22
|
+
s.coproc my_sleep(3)
|
23
23
|
end
|
24
24
|
puts "#{Time.now} woke up with #{result.inspect}"
|
data/examples/core/thread.rb
CHANGED
@@ -18,8 +18,8 @@ end
|
|
18
18
|
|
19
19
|
def threaded
|
20
20
|
t0 = Time.now
|
21
|
-
data = Polyphony::Thread.
|
22
|
-
X.times { Polyphony::Thread.
|
21
|
+
data = Polyphony::Thread.coproc { lengthy_op }.await
|
22
|
+
X.times { Polyphony::Thread.coproc { lengthy_op }.await }
|
23
23
|
puts "read threaded #{data.bytesize} bytes (#{Time.now - t0}s)"
|
24
24
|
end
|
25
25
|
|
@@ -13,10 +13,10 @@ def lengthy_op
|
|
13
13
|
acc / count
|
14
14
|
end
|
15
15
|
|
16
|
-
|
16
|
+
coproc do
|
17
17
|
t0 = Time.now
|
18
18
|
cancel_after(0.01) do
|
19
|
-
data = Polyphony::Thread.
|
19
|
+
data = Polyphony::Thread.coproc { lengthy_op }.await
|
20
20
|
puts "read #{data.bytesize} bytes (#{Time.now - t0}s)"
|
21
21
|
end
|
22
22
|
rescue Exception => e
|