polyphony 0.87 → 0.91
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/test_io_uring.yml +8 -4
- data/CHANGELOG.md +18 -0
- data/Gemfile.lock +1 -1
- data/examples/pipes/echo_server.rb +17 -0
- data/examples/pipes/gunzip.rb +6 -0
- data/examples/pipes/gzip.rb +6 -0
- data/examples/pipes/gzip_http_server.rb +49 -0
- data/examples/pipes/tcp_proxy.rb +28 -0
- data/examples/pipes/tee.rb +15 -0
- data/ext/polyphony/backend_common.c +10 -10
- data/ext/polyphony/backend_io_uring.c +175 -51
- data/ext/polyphony/backend_libev.c +25 -25
- data/ext/polyphony/extconf.rb +4 -2
- data/ext/polyphony/io_extensions.c +132 -57
- data/ext/polyphony/polyphony.c +12 -9
- data/ext/polyphony/polyphony.h +7 -0
- data/ext/polyphony/queue.c +3 -3
- data/ext/polyphony/socket_extensions.c +2 -2
- data/lib/polyphony/extensions/io.rb +4 -0
- data/lib/polyphony/version.rb +1 -1
- data/test/stress.rb +1 -1
- data/test/test_io.rb +229 -9
- data/test/test_signal.rb +6 -2
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d1b4a68e893c4cdca8e308cf3297fbf2549f70c0a7038f7c492f5c7c0a6ca6b4
|
4
|
+
data.tar.gz: 65a1cd1b10fa1a29c37c24972c0a47c324f744ff0ddba6e67464000da2a2707e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 316969779f3e2ce5a055c886ee89448b1908e57dcfb06775f5aa01491e895b450cfdaa3ec3d1f72f3a59017326dd7c3478b21e85cb7914a8bf2c17544bd47de7
|
7
|
+
data.tar.gz: 0a5badc5927cac1b111a13dd65eac242e2c2a7436dbf9a42e2376c4b321d042e27012e7d6b3906bf1d434d62a85bbfa8651700f2d4585475cbf89bc52de64569
|
@@ -8,15 +8,19 @@ jobs:
|
|
8
8
|
fail-fast: false
|
9
9
|
matrix:
|
10
10
|
os: [ubuntu-latest]
|
11
|
-
ruby: [2.
|
11
|
+
ruby: ['2.7', '3.0', '3.1', 'head']
|
12
12
|
|
13
13
|
name: >-
|
14
14
|
${{matrix.os}}, ${{matrix.ruby}}
|
15
15
|
|
16
16
|
runs-on: ${{matrix.os}}
|
17
17
|
steps:
|
18
|
-
-
|
19
|
-
|
18
|
+
- name: Checkout repository and submodules
|
19
|
+
uses: actions/checkout@v2
|
20
|
+
with:
|
21
|
+
submodules: recursive
|
22
|
+
- name: Setup Ruby
|
23
|
+
uses: ruby/setup-ruby@v1
|
20
24
|
with:
|
21
25
|
ruby-version: ${{matrix.ruby}}
|
22
26
|
bundler-cache: true # 'bundle install' and cache
|
@@ -29,4 +33,4 @@ jobs:
|
|
29
33
|
- name: Compile C-extension
|
30
34
|
run: bundle exec rake compile
|
31
35
|
- name: Run tests
|
32
|
-
run: bundle exec
|
36
|
+
run: bundle exec ruby test/run.rb --verbose --name test_sleep
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
## 0.91 2022-03-23
|
2
|
+
|
3
|
+
- Add pipe examples
|
4
|
+
- Implement `Backend#double_splice_to_eof` (io_ring only)
|
5
|
+
- Improve safety of tracing
|
6
|
+
|
7
|
+
## 0.90 2022-03-21
|
8
|
+
|
9
|
+
- Fix possible compilation error on Ruby 2.7.5 (#79)
|
10
|
+
|
11
|
+
## 0.89 2022-03-21
|
12
|
+
|
13
|
+
- Implement compression/decompression to/from strings (#86)
|
14
|
+
|
15
|
+
## 0.88 2022-03-18
|
16
|
+
|
17
|
+
- Improve IO stream compression utilities (release GVL, cleanup on exception)
|
18
|
+
|
1
19
|
## 0.87 2022-03-17
|
2
20
|
|
3
21
|
- Fix compilation on non-Linux OSes
|
data/Gemfile.lock
CHANGED
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'polyphony'
|
5
|
+
|
6
|
+
def handle_client(conn)
|
7
|
+
spin do
|
8
|
+
buffer = Polyphony.pipe
|
9
|
+
spin { IO.splice_to_eof(conn, buffer) }
|
10
|
+
IO.splice_to_eof(buffer, conn)
|
11
|
+
end
|
12
|
+
rescue SystemCallError
|
13
|
+
# ignore
|
14
|
+
end
|
15
|
+
|
16
|
+
puts "Serving echo on port 1234..."
|
17
|
+
TCPServer.new('127.0.0.1', 1234).accept_loop { |c| handle_client(c) }
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/inline'
|
4
|
+
|
5
|
+
gemfile do
|
6
|
+
gem 'h1p'
|
7
|
+
gem 'polyphony', path: '.'
|
8
|
+
end
|
9
|
+
|
10
|
+
require 'polyphony'
|
11
|
+
require 'h1p'
|
12
|
+
|
13
|
+
def handle_client(conn)
|
14
|
+
spin do
|
15
|
+
parser = H1P::Parser.new(conn, :server)
|
16
|
+
|
17
|
+
while true # assuming persistent connection
|
18
|
+
headers = parser.parse_headers
|
19
|
+
break unless headers
|
20
|
+
|
21
|
+
raw_buffer = Polyphony.pipe
|
22
|
+
gzip_buffer = Polyphony.pipe
|
23
|
+
|
24
|
+
# splice request body to buffer
|
25
|
+
spin do
|
26
|
+
parser.splice_body_to(raw_buffer)
|
27
|
+
raw_buffer.close
|
28
|
+
end
|
29
|
+
|
30
|
+
# zip data from buffer into gzip buffer
|
31
|
+
spin do
|
32
|
+
IO.gzip(raw_buffer, gzip_buffer)
|
33
|
+
gzip_buffer.close
|
34
|
+
end
|
35
|
+
|
36
|
+
# send headers and splice response from gzip buffer
|
37
|
+
conn << "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"
|
38
|
+
IO.http1_splice_chunked(gzip_buffer, conn, 65535)
|
39
|
+
end
|
40
|
+
rescue H1P::Error
|
41
|
+
puts 'Got invalid request, closing connection...'
|
42
|
+
ensure
|
43
|
+
conn.close
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
puts "Serving echo on port 1234..."
|
48
|
+
TCPServer.new('127.0.0.1', 1234).accept_loop { |c| handle_client(c) }
|
49
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'polyphony'
|
5
|
+
|
6
|
+
DESTINATION = ['127.0.0.1', 1234]
|
7
|
+
|
8
|
+
def handle_client(conn)
|
9
|
+
spin do
|
10
|
+
dest = TCPSocket.new(*DESTINATION)
|
11
|
+
w_buffer = Polyphony.pipe
|
12
|
+
r_buffer = Polyphony.pipe
|
13
|
+
|
14
|
+
spin { IO.splice_to_eof(conn, w_buffer) }
|
15
|
+
spin { IO.splice_to_eof(w_buffer, dest) }
|
16
|
+
|
17
|
+
spin { IO.splice_to_eof(dest, r_buffer) }
|
18
|
+
spin { IO.splice_to_eof(r_buffer, conn) }
|
19
|
+
|
20
|
+
Fiber.current.await_all_children
|
21
|
+
end
|
22
|
+
rescue SystemCallError
|
23
|
+
dest.close rescue nil
|
24
|
+
# ignore
|
25
|
+
end
|
26
|
+
|
27
|
+
puts "Serving TCP proxy on port 4321..."
|
28
|
+
TCPServer.new('127.0.0.1', 4321).accept_loop { |c| handle_client(c) }
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'polyphony'
|
5
|
+
|
6
|
+
chunk_size = 1 << 16
|
7
|
+
file_path = ARGV[0]
|
8
|
+
|
9
|
+
File.open(file_path, 'w+') do |f|
|
10
|
+
loop do
|
11
|
+
len = IO.tee(STDIN, STDOUT, chunk_size)
|
12
|
+
break if len == 0
|
13
|
+
IO.splice(STDIN, f, len)
|
14
|
+
end
|
15
|
+
end
|
@@ -140,7 +140,9 @@ inline void backend_base_unpark_fiber(struct Backend_base *base, VALUE fiber) {
|
|
140
140
|
inline void backend_trace(struct Backend_base *base, int argc, VALUE *argv) {
|
141
141
|
if (base->trace_proc == Qnil || base->in_trace_proc) return;
|
142
142
|
|
143
|
+
base->in_trace_proc = 1;
|
143
144
|
rb_funcallv(base->trace_proc, ID_call, argc, argv);
|
145
|
+
base->in_trace_proc = 0;
|
144
146
|
}
|
145
147
|
|
146
148
|
#ifdef POLYPHONY_USE_PIDFD_OPEN
|
@@ -363,8 +365,6 @@ inline void set_fd_blocking_mode(int fd, int blocking) {
|
|
363
365
|
}
|
364
366
|
|
365
367
|
inline void io_verify_blocking_mode(rb_io_t *fptr, VALUE io, VALUE blocking) {
|
366
|
-
int flags;
|
367
|
-
int is_nonblocking;
|
368
368
|
VALUE blocking_mode = rb_ivar_get(io, ID_ivar_blocking_mode);
|
369
369
|
if (blocking == blocking_mode) return;
|
370
370
|
|
@@ -418,13 +418,13 @@ VALUE Backend_stats(VALUE self) {
|
|
418
418
|
struct backend_stats backend_stats = backend_get_stats(self);
|
419
419
|
|
420
420
|
VALUE stats = rb_hash_new();
|
421
|
-
rb_hash_aset(stats, SYM_runqueue_size,
|
422
|
-
rb_hash_aset(stats, SYM_runqueue_length,
|
423
|
-
rb_hash_aset(stats, SYM_runqueue_max_length,
|
424
|
-
rb_hash_aset(stats, SYM_op_count,
|
425
|
-
rb_hash_aset(stats, SYM_switch_count,
|
426
|
-
rb_hash_aset(stats, SYM_poll_count,
|
427
|
-
rb_hash_aset(stats, SYM_pending_ops,
|
421
|
+
rb_hash_aset(stats, SYM_runqueue_size, INT2FIX(backend_stats.runqueue_size));
|
422
|
+
rb_hash_aset(stats, SYM_runqueue_length, INT2FIX(backend_stats.runqueue_length));
|
423
|
+
rb_hash_aset(stats, SYM_runqueue_max_length, INT2FIX(backend_stats.runqueue_max_length));
|
424
|
+
rb_hash_aset(stats, SYM_op_count, INT2FIX(backend_stats.op_count));
|
425
|
+
rb_hash_aset(stats, SYM_switch_count, INT2FIX(backend_stats.switch_count));
|
426
|
+
rb_hash_aset(stats, SYM_poll_count, INT2FIX(backend_stats.poll_count));
|
427
|
+
rb_hash_aset(stats, SYM_pending_ops, INT2FIX(backend_stats.pending_ops));
|
428
428
|
RB_GC_GUARD(stats);
|
429
429
|
return stats;
|
430
430
|
}
|
@@ -481,7 +481,7 @@ struct io_buffer get_io_buffer(VALUE in) {
|
|
481
481
|
struct raw_buffer *raw = FIX2PTR(in);
|
482
482
|
return (struct io_buffer){ raw->ptr, raw->len, 1 };
|
483
483
|
}
|
484
|
-
return (struct io_buffer){ RSTRING_PTR(in), RSTRING_LEN(in), 0 };
|
484
|
+
return (struct io_buffer){ (unsigned char *)RSTRING_PTR(in), RSTRING_LEN(in), 0 };
|
485
485
|
}
|
486
486
|
|
487
487
|
VALUE coerce_io_string_or_buffer(VALUE buf) {
|