uringmachine 0.31.0 → 0.32.0
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 +4 -0
- data/README.md +36 -37
- data/TODO.md +18 -55
- data/benchmark/bm_io_pipe.rb +2 -2
- data/benchmark/common.rb +16 -16
- data/benchmark/gets.rb +7 -7
- data/benchmark/gets_concurrent.rb +12 -12
- data/benchmark/http_parse.rb +11 -11
- data/benchmark/http_server_accept_queue.rb +7 -7
- data/benchmark/http_server_multi_accept.rb +7 -7
- data/benchmark/http_server_multi_ractor.rb +7 -7
- data/benchmark/http_server_single_thread.rb +8 -8
- data/benchmark/openssl.rb +4 -4
- data/examples/fiber_concurrency_io.rb +1 -1
- data/examples/fiber_concurrency_um.rb +16 -0
- data/examples/io_uring_simple.c +13 -4
- data/examples/pg.rb +2 -2
- data/examples/um_cancellation.rb +20 -0
- data/examples/um_fiber_scheduler.rb +10 -0
- data/examples/um_io.rb +19 -0
- data/examples/um_mo.c +32 -0
- data/examples/um_multishot.rb +15 -0
- data/examples/um_ssl.rb +11 -0
- data/ext/um/um.h +19 -19
- data/ext/um/um_ext.c +2 -4
- data/ext/um/{um_connection.c → um_io.c} +210 -210
- data/ext/um/{um_connection_class.c → um_io_class.c} +102 -102
- data/lib/uringmachine/version.rb +1 -1
- data/lib/uringmachine.rb +12 -12
- data/test/{test_connection.rb → test_io.rb} +29 -29
- data/test/test_um.rb +7 -7
- metadata +13 -6
data/benchmark/openssl.rb
CHANGED
|
@@ -81,7 +81,7 @@ end
|
|
|
81
81
|
@um.ssl_set_bio(@ssl_conn)
|
|
82
82
|
@ssl_conn.connect
|
|
83
83
|
|
|
84
|
-
@
|
|
84
|
+
@io = @um.io(@ssl_conn)
|
|
85
85
|
|
|
86
86
|
@msg = 'abc' * 1000
|
|
87
87
|
@msg_newline = @msg + "\n"
|
|
@@ -91,15 +91,15 @@ def do_io(ssl)
|
|
|
91
91
|
ssl.gets
|
|
92
92
|
end
|
|
93
93
|
|
|
94
|
-
def
|
|
94
|
+
def do_io_io(ssl, um, io)
|
|
95
95
|
um.ssl_write(ssl, @msg_newline, 0)
|
|
96
|
-
|
|
96
|
+
io.read_line(0)
|
|
97
97
|
end
|
|
98
98
|
|
|
99
99
|
Benchmark.ips do |x|
|
|
100
100
|
x.report('stock') { do_io(@ssl_stock) }
|
|
101
101
|
x.report('UM BIO') { do_io(@ssl_um) }
|
|
102
|
-
x.report('UM
|
|
102
|
+
x.report('UM::IO') { do_io_io(@ssl_conn, @um, @io) }
|
|
103
103
|
|
|
104
104
|
x.compare!(order: :baseline)
|
|
105
105
|
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require 'uringmachine'
|
|
2
|
+
|
|
3
|
+
machine = UM.new
|
|
4
|
+
|
|
5
|
+
reader = machine.spin {
|
|
6
|
+
input = +''
|
|
7
|
+
machine.read(UM::STDIN_FILENO, input, 256)
|
|
8
|
+
machine.write(UM::STDOUT_FILENO, "Got: #{input}")
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
sleeper = machine.spin {
|
|
12
|
+
machine.sleep(5)
|
|
13
|
+
machine.write(UM::STDOUT_FILENO, "5 seconds have elapsed!")
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
machine.join(reader, sleeper)
|
data/examples/io_uring_simple.c
CHANGED
|
@@ -7,6 +7,7 @@ int ret;
|
|
|
7
7
|
char buf[100];
|
|
8
8
|
|
|
9
9
|
ret = io_uring_queue_init(8, &ring, 0);
|
|
10
|
+
|
|
10
11
|
sqe = io_uring_get_sqe(&ring);
|
|
11
12
|
io_uring_prep_read(sqe, STDIN_FILENO, buf, 100, 0);
|
|
12
13
|
sqe->user_data = 42;
|
|
@@ -14,11 +15,19 @@ io_uring_submit(&ring);
|
|
|
14
15
|
|
|
15
16
|
...
|
|
16
17
|
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
sqe = io_uring_get_sqe(&ring);
|
|
19
|
+
io_uring_prep_cancel(sqe, 42, IORING_ASYNC_CANCEL_USERDATA);
|
|
20
|
+
sqe->flags = IOSQE_CQE_SKIP_SUCCESS;
|
|
21
|
+
io_uring_submit(&ring);
|
|
22
|
+
|
|
23
|
+
if (!io_uring_wait_cqe(&ring, &cqe)) {
|
|
19
24
|
if (cqe->user_data == 42) {
|
|
20
|
-
|
|
21
|
-
|
|
25
|
+
if (cqe->res == -ECANCELED)
|
|
26
|
+
printf("Cancelled!\n");
|
|
27
|
+
else {
|
|
28
|
+
int len = cqe->res;
|
|
29
|
+
printf("Got %d bytes\n", len);
|
|
30
|
+
}
|
|
22
31
|
}
|
|
23
32
|
io_uring_cqe_seen(&ring, cqe);
|
|
24
33
|
}
|
data/examples/pg.rb
CHANGED
|
@@ -66,9 +66,9 @@ $machine.listen(server_fd, UM::SOMAXCONN)
|
|
|
66
66
|
puts 'Listening on port 1234'
|
|
67
67
|
|
|
68
68
|
def handle_connection(fd)
|
|
69
|
-
|
|
69
|
+
io = UM::IO.new($machine, fd)
|
|
70
70
|
|
|
71
|
-
while (l =
|
|
71
|
+
while (l = io.gets)
|
|
72
72
|
$machine.write(fd, "You said: #{l}")
|
|
73
73
|
end
|
|
74
74
|
rescue Exception => e
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
f = machine.spin do
|
|
2
|
+
buf = +''
|
|
3
|
+
machine.read(fd, buf, 256)
|
|
4
|
+
machine.write(UM::STDOUT_FILENO, "Got: #{buf}")
|
|
5
|
+
rescue UM::Terminate
|
|
6
|
+
machine.write(UM::STDOUT_FILENO, "Cancelled")
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
machine.sleep(0.1)
|
|
10
|
+
machine.schedule(f, UM::Terminate.new)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# read with timeout
|
|
16
|
+
input = +''
|
|
17
|
+
machine.timeout(timeout, TimeoutError) {
|
|
18
|
+
machine.read(fd, input, 256)
|
|
19
|
+
}
|
|
20
|
+
|
data/examples/um_io.rb
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
io = machine.io(fd)
|
|
2
|
+
|
|
3
|
+
# parse an incoming HTTP request
|
|
4
|
+
line = io.read_line(4096)
|
|
5
|
+
m = line.match(/^([a-z]+)\s+([^\s]+)\s+(http\/1\.1)/i)
|
|
6
|
+
headers = {
|
|
7
|
+
':method' => m[1].downcase,
|
|
8
|
+
':path' => m[2],
|
|
9
|
+
':protocol' => m[3].downcase
|
|
10
|
+
}
|
|
11
|
+
while true
|
|
12
|
+
line = io.read_line(4096)
|
|
13
|
+
break if line.empty?
|
|
14
|
+
|
|
15
|
+
m = line.match(/^([a-z0-9\-]+)\:\s+(.+)/i)
|
|
16
|
+
headers[m[1].downcase] = m[2]
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
io.write("HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nfoo")
|
data/examples/um_mo.c
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
VALUE um_sleep(struct um *machine, double duration) {
|
|
2
|
+
struct um_op *op = um_op_acquire(machine);
|
|
3
|
+
op->fiber = rb_fiber_current();
|
|
4
|
+
op->ts = um_double_to_timespec(duration);
|
|
5
|
+
struct io_uring_sqe *sqe = um_get_sqe(machine, op);
|
|
6
|
+
io_uring_prep_timeout(sqe, &op->ts, 0, 0);
|
|
7
|
+
|
|
8
|
+
VALUE ret = um_switch(machine);
|
|
9
|
+
if (um_verify_op_completion(machine, op)) ret = DBL2NUM(duration);
|
|
10
|
+
um_op_release(machine, op);
|
|
11
|
+
|
|
12
|
+
RAISE_IF_EXCEPTION(ret);
|
|
13
|
+
return ret;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
VALUE um_switch(struct um *machine) {
|
|
17
|
+
while (true) {
|
|
18
|
+
struct um_op *op = um_runqueue_shift(machine);
|
|
19
|
+
if (op) return rb_fiber_transfer(op->fiber, 1, &op->value);
|
|
20
|
+
|
|
21
|
+
um_wait_for_and_process_ready_cqes(machine);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
void um_process_cqe(struct um *machine, struct io_uring_cqe *cqe) {
|
|
26
|
+
struct um_op *op = (struct um_op *)cqe->user_data;
|
|
27
|
+
if (op) {
|
|
28
|
+
op->result.res = cqe->res;
|
|
29
|
+
op->result.flags = cqe->flags;
|
|
30
|
+
um_runqueue_push(machine, op);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# singleshot accept
|
|
2
|
+
while (fd = machine.accept(server_fd))
|
|
3
|
+
handle_connection(fd)
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
# multishot accept
|
|
7
|
+
machine.accept_each(server_fd) { handle_connection(it) }
|
|
8
|
+
|
|
9
|
+
# multishot timeout
|
|
10
|
+
machine.periodically(5) { ... }
|
|
11
|
+
|
|
12
|
+
# multishot recv
|
|
13
|
+
machine.recv_each(fd, 0) { |data|
|
|
14
|
+
machine.write(UM::STDOUT_FILENO, "Got: #{data}\n")
|
|
15
|
+
}
|
data/examples/um_ssl.rb
ADDED
data/ext/um/um.h
CHANGED
|
@@ -80,12 +80,12 @@ enum um_op_kind {
|
|
|
80
80
|
OP_TIMEOUT_MULTISHOT,
|
|
81
81
|
};
|
|
82
82
|
|
|
83
|
-
enum
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
83
|
+
enum um_io_mode {
|
|
84
|
+
IO_FD,
|
|
85
|
+
IO_SOCKET,
|
|
86
|
+
IO_SSL,
|
|
87
|
+
IO_STRING,
|
|
88
|
+
IO_IO_BUFFER
|
|
89
89
|
};
|
|
90
90
|
|
|
91
91
|
#define OP_F_CQE_SEEN (1U << 0) // CQE has been seen
|
|
@@ -272,11 +272,11 @@ struct um_async_op {
|
|
|
272
272
|
struct um_op *op;
|
|
273
273
|
};
|
|
274
274
|
|
|
275
|
-
struct
|
|
275
|
+
struct um_io {
|
|
276
276
|
VALUE self;
|
|
277
277
|
struct um *machine;
|
|
278
278
|
|
|
279
|
-
enum
|
|
279
|
+
enum um_io_mode mode;
|
|
280
280
|
union {
|
|
281
281
|
int fd;
|
|
282
282
|
VALUE target;
|
|
@@ -304,7 +304,7 @@ extern VALUE eUMError;
|
|
|
304
304
|
extern VALUE cMutex;
|
|
305
305
|
extern VALUE cQueue;
|
|
306
306
|
extern VALUE cAsyncOp;
|
|
307
|
-
extern VALUE
|
|
307
|
+
extern VALUE eIORESPError;
|
|
308
308
|
|
|
309
309
|
struct um *um_get_machine(VALUE self);
|
|
310
310
|
void um_setup(VALUE self, struct um *machine, uint size, uint sqpoll_timeout_msec, int sidecar_mode);
|
|
@@ -438,16 +438,16 @@ VALUE um_queue_pop(struct um *machine, struct um_queue *queue);
|
|
|
438
438
|
VALUE um_queue_unshift(struct um *machine, struct um_queue *queue, VALUE value);
|
|
439
439
|
VALUE um_queue_shift(struct um *machine, struct um_queue *queue);
|
|
440
440
|
|
|
441
|
-
void
|
|
442
|
-
void
|
|
443
|
-
VALUE
|
|
444
|
-
VALUE
|
|
445
|
-
VALUE
|
|
446
|
-
void
|
|
447
|
-
void
|
|
448
|
-
size_t
|
|
449
|
-
VALUE
|
|
450
|
-
VALUE resp_read(struct
|
|
441
|
+
void io_teardown(struct um_io *io);
|
|
442
|
+
void io_clear(struct um_io *io);
|
|
443
|
+
VALUE io_read_line(struct um_io *io, VALUE out_buffer, size_t maxlen);
|
|
444
|
+
VALUE io_read(struct um_io *io, VALUE out_buffer, ssize_t len, size_t inc, int safe_inc);
|
|
445
|
+
VALUE io_read_to_delim(struct um_io *io, VALUE out_buffer, VALUE delim, ssize_t maxlen);
|
|
446
|
+
void io_skip(struct um_io *io, size_t inc, int safe_inc);
|
|
447
|
+
void io_read_each(struct um_io *io);
|
|
448
|
+
size_t io_write_raw(struct um_io *io, const char *buffer, size_t len);
|
|
449
|
+
VALUE io_writev(struct um_io *io, int argc, VALUE *argv);
|
|
450
|
+
VALUE resp_read(struct um_io *io, VALUE out_buffer);
|
|
451
451
|
void resp_encode(struct um_write_buffer *buf, VALUE obj);
|
|
452
452
|
void resp_encode_cmd(struct um_write_buffer *buf, int argc, VALUE *argv);
|
|
453
453
|
|
data/ext/um/um_ext.c
CHANGED
|
@@ -2,14 +2,12 @@ void Init_UM();
|
|
|
2
2
|
void Init_Mutex();
|
|
3
3
|
void Init_Queue();
|
|
4
4
|
void Init_AsyncOp();
|
|
5
|
-
void
|
|
6
|
-
void Init_Stream();
|
|
5
|
+
void Init_IO();
|
|
7
6
|
|
|
8
7
|
void Init_um_ext(void) {
|
|
9
8
|
Init_UM();
|
|
10
9
|
Init_Mutex();
|
|
11
10
|
Init_Queue();
|
|
12
11
|
Init_AsyncOp();
|
|
13
|
-
|
|
14
|
-
Init_Stream();
|
|
12
|
+
Init_IO();
|
|
15
13
|
}
|