polyphony 0.16 → 0.17
Sign up to get free protection for your applications and to get access to all the features.
- 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
|