polyphony 0.17 → 0.19
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 +15 -0
- data/Gemfile.lock +11 -3
- data/README.md +18 -18
- data/TODO.md +5 -21
- 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_cancel.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 +4 -4
- data/examples/core/supervisor.rb +1 -1
- data/examples/core/supervisor_with_error.rb +1 -1
- data/examples/core/supervisor_with_manual_move_on.rb +1 -1
- data/examples/core/thread.rb +2 -2
- data/examples/core/thread_cancel.rb +2 -2
- data/examples/core/thread_pool.rb +1 -1
- data/examples/core/throttle.rb +3 -3
- data/examples/core/timeout.rb +10 -0
- data/examples/fs/read.rb +1 -1
- data/examples/http/http_client.rb +1 -1
- data/examples/http/http_get.rb +7 -0
- data/examples/http/http_parse_experiment.rb +118 -0
- data/examples/http/http_proxy.rb +81 -0
- data/examples/http/http_server.rb +15 -4
- data/examples/http/http_server_forked.rb +2 -2
- data/examples/http/http_server_throttled.rb +1 -1
- data/examples/http/http_ws_server.rb +2 -2
- data/examples/http/https_server.rb +5 -1
- data/examples/http/https_wss_server.rb +1 -1
- data/examples/http/rack_server_https_forked.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/echo_client.rb +2 -2
- data/examples/io/echo_pipe.rb +17 -0
- data/examples/io/echo_server.rb +1 -1
- data/examples/io/echo_server_with_timeout.rb +1 -1
- data/examples/io/httparty.rb +10 -0
- data/examples/io/httparty_multi.rb +29 -0
- data/examples/io/httparty_threaded.rb +25 -0
- data/examples/io/irb.rb +15 -0
- data/examples/io/net-http.rb +15 -0
- data/examples/io/system.rb +1 -1
- data/examples/io/tcpsocket.rb +18 -0
- data/examples/performance/perf_multi_snooze.rb +2 -2
- data/examples/performance/perf_snooze.rb +17 -20
- data/examples/performance/thread-vs-fiber/polyphony_server.rb +1 -1
- data/ext/ev/ev.h +9 -1
- data/ext/ev/ev_ext.c +4 -1
- data/ext/ev/ev_module.c +36 -22
- data/ext/ev/extconf.rb +1 -1
- data/ext/ev/io.c +23 -23
- data/ext/ev/signal.c +1 -1
- data/ext/ev/socket.c +161 -0
- data/lib/polyphony/core/coprocess.rb +1 -1
- data/lib/polyphony/core/fiber_pool.rb +2 -2
- data/lib/polyphony/core/supervisor.rb +2 -18
- data/lib/polyphony/extensions/io.rb +19 -6
- data/lib/polyphony/extensions/kernel.rb +17 -5
- data/lib/polyphony/extensions/socket.rb +40 -1
- data/lib/polyphony/http/agent.rb +56 -25
- data/lib/polyphony/http/http1_adapter.rb +254 -0
- data/lib/polyphony/http/http2_adapter.rb +157 -0
- data/lib/polyphony/http/{http2_request.rb → request.rb} +25 -22
- data/lib/polyphony/http/server.rb +19 -11
- data/lib/polyphony/net.rb +10 -6
- data/lib/polyphony/version.rb +1 -1
- data/polyphony.gemspec +6 -5
- data/test/test_coprocess.rb +9 -9
- data/test/test_core.rb +14 -14
- data/test/test_io.rb +4 -4
- data/test/test_kernel.rb +1 -1
- metadata +48 -23
- data/lib/polyphony/http/http1.rb +0 -124
- data/lib/polyphony/http/http1_request.rb +0 -83
- data/lib/polyphony/http/http2.rb +0 -65
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e79ca0a896fc0b5feffa415e44b9229074d145c2142155caf47f243b6c85078d
|
4
|
+
data.tar.gz: 6aa58f404376be6e6d472e588be4349d6fcaeb3031e5786a0a5ffe0970d9fa5d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: accbeddc33fd7b1de40f411a421c445bc847e8ee744d98dcd1cf20b0a8fe3fc5c880ca373a020b026a0d68aac9cfc74f179bde2c3cebd1b0733a5adbe2b435b0
|
7
|
+
data.tar.gz: 7549c7ac4528bf4747049fb6c4eecbfe500f6aeed3586f8181bbf21506f8725ebb51c1170e369f15b24c748d59be439a2d076d26de1e5b1a1b6b34ae3e344ade
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
0.19 2019-06-12
|
2
|
+
---------------
|
3
|
+
|
4
|
+
* Rewrite HTTP server for better concurrency, sequential API
|
5
|
+
* Support 204 no-content response in HTTP 1
|
6
|
+
* Add optional count parameter to Kernel#throttled_loop for finite looping
|
7
|
+
* Implement Fiber#safe_transfer in C
|
8
|
+
* Optimize Kernel#next_tick implementation using ev_idle instead of ev_timer
|
9
|
+
|
10
|
+
0.18 2019-06-08
|
11
|
+
---------------
|
12
|
+
|
13
|
+
* Rename Kernel#coproc to Kernel#spin
|
14
|
+
* Rewrite Supervisor#spin
|
15
|
+
|
1
16
|
0.17 2019-05-24
|
2
17
|
---------------
|
3
18
|
|
data/Gemfile.lock
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
polyphony (0.
|
4
|
+
polyphony (0.19)
|
5
5
|
http-2 (= 0.10.0)
|
6
6
|
http_parser.rb (= 0.6.0)
|
7
|
-
modulation (
|
7
|
+
modulation (~> 0.25)
|
8
8
|
|
9
9
|
GEM
|
10
10
|
remote: https://rubygems.org/
|
@@ -12,9 +12,16 @@ GEM
|
|
12
12
|
hiredis (0.6.3)
|
13
13
|
http-2 (0.10.0)
|
14
14
|
http_parser.rb (0.6.0)
|
15
|
+
httparty (0.17.0)
|
16
|
+
mime-types (~> 3.0)
|
17
|
+
multi_xml (>= 0.5.2)
|
15
18
|
localhost (1.1.4)
|
19
|
+
mime-types (3.2.2)
|
20
|
+
mime-types-data (~> 3.2015)
|
21
|
+
mime-types-data (3.2019.0331)
|
16
22
|
minitest (5.11.3)
|
17
|
-
modulation (0.
|
23
|
+
modulation (0.25)
|
24
|
+
multi_xml (0.6.0)
|
18
25
|
pg (1.1.3)
|
19
26
|
rake (12.3.2)
|
20
27
|
rake-compiler (1.0.5)
|
@@ -27,6 +34,7 @@ PLATFORMS
|
|
27
34
|
|
28
35
|
DEPENDENCIES
|
29
36
|
hiredis (= 0.6.3)
|
37
|
+
httparty (= 0.17.0)
|
30
38
|
localhost (= 1.1.4)
|
31
39
|
minitest (= 5.11.3)
|
32
40
|
pg (= 1.1.3)
|
data/README.md
CHANGED
@@ -11,8 +11,8 @@
|
|
11
11
|
> number of parts, each forming an individual melody and harmonizing with each
|
12
12
|
> other.
|
13
13
|
|
14
|
-
**Note**: Polyphony is designed to work with recent
|
15
|
-
|
14
|
+
**Note**: Polyphony is experimental software. It is designed to work with recent
|
15
|
+
versions of Ruby (2.5 and newer) and supports Linux and MacOS only.
|
16
16
|
|
17
17
|
## What is Polyphony
|
18
18
|
|
@@ -41,7 +41,7 @@ takes care of context-switching automatically whenever a blocking call like
|
|
41
41
|
coprocesses, supervisors, cancel scopes, throttling, resource pools etc.
|
42
42
|
- Code can use native networking classes and libraries, growing support for
|
43
43
|
third-party gems such as `pg` and `redis`.
|
44
|
-
- HTTP 1 / HTTP 2 client
|
44
|
+
- HTTP 1 / HTTP 2 client agent with persistent connections.
|
45
45
|
- Competitive performance and scalability characteristics, in terms of both
|
46
46
|
throughput and memory consumption.
|
47
47
|
|
@@ -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#spin`:
|
74
74
|
|
75
75
|
```ruby
|
76
76
|
require 'polyphony'
|
77
77
|
|
78
|
-
|
78
|
+
spin 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
|
+
spin 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 `spin` 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
|
@@ -99,8 +99,8 @@ any boilerplate relating to concurrency. Each `coproc` block starts a
|
|
99
99
|
> called, and resumed once that operation has been completed. Coprocesses offer
|
100
100
|
> significant advantages over threads - they consume only about 10KB, switching
|
101
101
|
> between them is much faster than switching threads, and literally millions of
|
102
|
-
> them can be
|
103
|
-
> allow parallel execution of threads.
|
102
|
+
> them can be spinned off without affecting performance*. Besides, Ruby does not
|
103
|
+
> yet allow parallel execution of threads (courtesy of the Ruby GVL).
|
104
104
|
>
|
105
105
|
> \* *This is a totally unsubstantiated claim which has not been proved in
|
106
106
|
> practice*.
|
@@ -116,7 +116,7 @@ require 'polyphony'
|
|
116
116
|
server = TCPServer.open(1234)
|
117
117
|
while client = server.accept
|
118
118
|
# coproc starts a new coprocess on a separate fiber
|
119
|
-
|
119
|
+
spin {
|
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#spin`,
|
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
|
@@ -223,7 +223,7 @@ end
|
|
223
223
|
### Additional concurrency constructs
|
224
224
|
|
225
225
|
In order to facilitate writing concurrent code, Polyphony provides additional
|
226
|
-
constructs that make it easier to
|
226
|
+
constructs that make it easier to create and control concurrent tasks.
|
227
227
|
|
228
228
|
`CancelScope` - an abstraction used to cancel the execution of one or more
|
229
229
|
coprocesses or supervisors. It usually works by defining a timeout for the
|
@@ -257,7 +257,7 @@ Pool = Polyphony::ResourcePool.new(limit: 5) {
|
|
257
257
|
}
|
258
258
|
|
259
259
|
1000.times {
|
260
|
-
|
260
|
+
spin {
|
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
|
+
spin { p Pool.query('select 1') }
|
278
278
|
}
|
279
279
|
```
|
280
280
|
|
@@ -285,9 +285,9 @@ using `Kernel.supervise`:
|
|
285
285
|
|
286
286
|
```ruby
|
287
287
|
supervise { |s|
|
288
|
-
s.
|
289
|
-
s.
|
290
|
-
s.
|
288
|
+
s.spin { sleep 1 }
|
289
|
+
s.spin { sleep 2 }
|
290
|
+
s.spin { sleep 3 }
|
291
291
|
}
|
292
292
|
puts "done sleeping"
|
293
293
|
```
|
@@ -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
|
+
spin {
|
317
317
|
throttler.call {
|
318
318
|
while data = client.read
|
319
319
|
client.write(data)
|
data/TODO.md
CHANGED
@@ -1,42 +1,26 @@
|
|
1
1
|
# Roadmap:
|
2
2
|
|
3
|
-
## 0.
|
4
|
-
|
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)
|
11
|
-
|
12
|
-
## 0.18 Working net/http, httparty
|
13
|
-
|
14
|
-
- implement `TCPSocket`/`TCPServer` functionality
|
15
|
-
- test `socket` classes
|
16
|
-
- test `Net::HTTP`
|
17
|
-
- test `httparty`
|
18
|
-
|
19
|
-
## 0.19 Full Rack adapter implementation
|
3
|
+
## 0.20 Full Rack adapter implementation
|
20
4
|
|
21
5
|
- follow Rack specification (doesn't have to include stuff like streaming or
|
22
6
|
websockets)
|
23
7
|
- find some demo Rack apps and test with Polyphony
|
24
8
|
|
25
|
-
## 0.
|
9
|
+
## 0.21 Working Rails application
|
26
10
|
|
27
11
|
- app with database access (postgresql)
|
28
12
|
- benchmarks!
|
29
13
|
|
30
|
-
## 0.
|
14
|
+
## 0.22 Support for multi-threading
|
31
15
|
|
32
16
|
- Separate event loop for each thread
|
33
17
|
|
34
|
-
## 0.
|
18
|
+
## 0.23 Testing
|
35
19
|
|
36
20
|
- test thread / thread_pool modules
|
37
21
|
- report test coverage
|
38
22
|
|
39
|
-
## 0.
|
23
|
+
## 0.24 Documentation
|
40
24
|
|
41
25
|
# DNS
|
42
26
|
|
@@ -14,9 +14,9 @@ end
|
|
14
14
|
|
15
15
|
chan1, chan2 = Polyphony::Channel.new, Polyphony::Channel.new
|
16
16
|
|
17
|
-
echoer =
|
17
|
+
echoer = spin { echo(chan1, chan2) }
|
18
18
|
|
19
|
-
|
19
|
+
spin 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 = spin 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/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 spin_with_error
|
13
|
+
spin { error(2) }
|
14
14
|
end
|
15
15
|
|
16
|
-
|
16
|
+
spin 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
|
+
spin_with_error
|
27
27
|
|
28
28
|
puts "done coprocing"
|
data/examples/core/supervisor.rb
CHANGED