uringmachine 0.10 → 0.11.1
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 +8 -0
- data/examples/bm_http_parse.rb +108 -35
- data/examples/bm_side_running.rb +83 -0
- data/examples/bm_sqlite.rb +1 -1
- data/ext/um/um.c +17 -1
- data/ext/um/um.h +30 -0
- data/ext/um/um_ext.c +2 -0
- data/ext/um/um_stream.c +372 -0
- data/ext/um/um_stream_class.c +121 -0
- data/lib/uringmachine/version.rb +1 -1
- data/lib/uringmachine.rb +20 -16
- data/test/test_stream.rb +133 -0
- data/test/test_um.rb +63 -0
- data/uringmachine.gemspec +1 -0
- data/vendor/liburing/.github/workflows/{build.yml → ci.yml} +107 -42
- data/vendor/liburing/.gitignore +1 -0
- data/vendor/liburing/CHANGELOG +10 -0
- data/vendor/liburing/README +5 -0
- data/vendor/liburing/configure +1 -1
- data/vendor/liburing/examples/Makefile +1 -0
- data/vendor/liburing/examples/helpers.c +25 -0
- data/vendor/liburing/examples/helpers.h +13 -0
- data/vendor/liburing/examples/io_uring-test.c +3 -0
- data/vendor/liburing/examples/proxy.c +1 -1
- data/vendor/liburing/examples/reg-wait.c +41 -6
- data/vendor/liburing/examples/send-zerocopy.c +79 -32
- data/vendor/liburing/examples/zcrx.c +436 -0
- data/vendor/liburing/liburing.spec +1 -1
- data/vendor/liburing/src/Makefile +0 -1
- data/vendor/liburing/src/arch/generic/syscall.h +2 -2
- data/vendor/liburing/src/arch/syscall-defs.h +2 -2
- data/vendor/liburing/src/include/liburing/io_uring.h +101 -17
- data/vendor/liburing/src/include/liburing.h +179 -59
- data/vendor/liburing/src/int_flags.h +4 -1
- data/vendor/liburing/src/liburing-ffi.map +14 -2
- data/vendor/liburing/src/liburing.map +9 -2
- data/vendor/liburing/src/queue.c +35 -30
- data/vendor/liburing/src/register.c +46 -15
- data/vendor/liburing/src/sanitize.c +6 -9
- data/vendor/liburing/src/setup.c +37 -71
- data/vendor/liburing/src/syscall.c +2 -2
- data/vendor/liburing/test/232c93d07b74.c +1 -0
- data/vendor/liburing/test/Makefile +9 -0
- data/vendor/liburing/test/accept-test.c +1 -0
- data/vendor/liburing/test/cmd-discard.c +16 -8
- data/vendor/liburing/test/connect.c +11 -7
- data/vendor/liburing/test/epwait.c +420 -0
- data/vendor/liburing/test/eventfd-ring.c +30 -5
- data/vendor/liburing/test/fallocate.c +1 -1
- data/vendor/liburing/test/fixed-hugepage.c +10 -7
- data/vendor/liburing/test/fixed-seg.c +187 -0
- data/vendor/liburing/test/helpers.c +121 -0
- data/vendor/liburing/test/helpers.h +13 -0
- data/vendor/liburing/test/init-mem.c +2 -0
- data/vendor/liburing/test/io_uring_passthrough.c +78 -62
- data/vendor/liburing/test/iopoll-overflow.c +5 -4
- data/vendor/liburing/test/iopoll.c +20 -10
- data/vendor/liburing/test/iowait.c +141 -0
- data/vendor/liburing/test/nvme.h +2 -0
- data/vendor/liburing/test/pipe-bug.c +11 -5
- data/vendor/liburing/test/pipe-eof.c +11 -1
- data/vendor/liburing/test/read-inc-file.c +150 -0
- data/vendor/liburing/test/read-write.c +21 -14
- data/vendor/liburing/test/recv-bundle-short-ooo.c +435 -0
- data/vendor/liburing/test/recv-multishot.c +2 -2
- data/vendor/liburing/test/reg-wait.c +449 -120
- data/vendor/liburing/test/regbuf-clone.c +53 -0
- data/vendor/liburing/test/resize-rings.c +25 -2
- data/vendor/liburing/test/rsrc_tags.c +67 -14
- data/vendor/liburing/test/send-zerocopy.c +52 -130
- data/vendor/liburing/test/sendmsg_iov_clean.c +216 -0
- data/vendor/liburing/test/socket-nb.c +158 -0
- data/vendor/liburing/test/sqwait.c +9 -11
- data/vendor/liburing/test/timeout.c +198 -0
- data/vendor/liburing/test/vec-regbuf.c +609 -0
- data/vendor/liburing/test/wait-timeout.c +1 -1
- data/vendor/liburing/test/wq-aff.c +5 -1
- data/vendor/liburing/test/zcrx.c +928 -0
- metadata +30 -4
- data/vendor/liburing/.github/workflows/codespell.yml +0 -25
- data/vendor/liburing/.github/workflows/shellcheck.yml +0 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ccb8488c3f313b7a3890ae110fc5cebc7ac0062bbaa9ef362fb7ff5b02c680b9
|
4
|
+
data.tar.gz: 41f2c23a9427609c4d01a6eef319cbd40d029cf85918fd6c8d00e5b502f83ef6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9bd08ebae21a7a10407ff04102d9cbf491bfab65ebe601b6ab3a6b7790632c946873415af4f45321e959bd39e875ff386e8c85f74329743204a9c0c047ce5da0
|
7
|
+
data.tar.gz: 3cd63222c0b990ef83f2b324aa46b36bd142a7b43a1a273428a9b70a95cfe25e0a1b06a2985a7463fe51a995c78e82838e34ee20d3c332cc46278ffd738652dd
|
data/CHANGELOG.md
CHANGED
data/examples/bm_http_parse.rb
CHANGED
@@ -1,16 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'bundler/inline'
|
3
|
+
# require 'bundler/inline'
|
4
4
|
|
5
|
-
gemfile do
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
end
|
5
|
+
# gemfile do
|
6
|
+
# source 'https://rubygems.org'
|
7
|
+
# gem 'uringmachine', path: '..'
|
8
|
+
# gem 'benchmark-ips'
|
9
|
+
# gem 'http_parser.rb'
|
10
|
+
# end
|
11
11
|
|
12
|
-
require '
|
12
|
+
require 'bundler/setup'
|
13
13
|
require 'uringmachine'
|
14
|
+
require 'benchmark/ips'
|
14
15
|
require 'http/parser'
|
15
16
|
|
16
17
|
$machine = UM.new
|
@@ -19,6 +20,8 @@ HTTP_MSG = "GET /foo/bar HTTP/1.1\r\nServer: foobar.com\r\nFoo: bar\r\n\r\n"
|
|
19
20
|
|
20
21
|
$count = 0
|
21
22
|
|
23
|
+
STDOUT.sync = true
|
24
|
+
|
22
25
|
def parse_http_parser
|
23
26
|
current_fiber = Fiber.current
|
24
27
|
$count += 1
|
@@ -45,10 +48,16 @@ def parse_http_parser
|
|
45
48
|
end
|
46
49
|
|
47
50
|
$machine.write(w.fileno, HTTP_MSG)
|
48
|
-
$machine.yield
|
51
|
+
ret = $machine.yield
|
52
|
+
ret
|
53
|
+
rescue Exception => e
|
54
|
+
p e: e
|
55
|
+
exit
|
49
56
|
ensure
|
50
|
-
|
51
|
-
|
57
|
+
r.close rescue nil
|
58
|
+
w.close rescue nil
|
59
|
+
# $machine.close(r.fileno) rescue nil
|
60
|
+
# $machine.close(w.fileno) rescue nil
|
52
61
|
end
|
53
62
|
|
54
63
|
require 'stringio'
|
@@ -100,50 +109,114 @@ def parse_headers(fd)
|
|
100
109
|
end
|
101
110
|
|
102
111
|
def parse_http_stringio
|
103
|
-
|
104
|
-
|
112
|
+
rfd, wfd = UM.pipe
|
113
|
+
queue = UM::Queue.new
|
105
114
|
|
106
115
|
$machine.spin do
|
107
|
-
headers = parse_headers(
|
108
|
-
$machine.
|
116
|
+
headers = parse_headers(rfd)
|
117
|
+
$machine.push(queue, headers)
|
109
118
|
rescue Exception => e
|
110
119
|
p e
|
111
120
|
puts e.backtrace.join("\n")
|
112
121
|
exit!
|
113
122
|
end
|
114
123
|
|
115
|
-
$machine.write(
|
116
|
-
$machine.
|
124
|
+
$machine.write(wfd, HTTP_MSG)
|
125
|
+
$machine.close(wfd)
|
126
|
+
$machine.shift(queue)
|
117
127
|
ensure
|
118
|
-
$machine.close(
|
119
|
-
$machine.close(
|
128
|
+
($machine.close(rfd) rescue nil) if rfd
|
129
|
+
($machine.close(wfd) rescue nil) if wfd
|
120
130
|
end
|
121
131
|
|
122
|
-
|
123
|
-
|
124
|
-
# exit
|
132
|
+
def stream_parse_headers(fd)
|
133
|
+
stream = UM::Stream.new($machine, fd)
|
125
134
|
|
126
|
-
|
135
|
+
headers = stream_get_request_line(stream)
|
136
|
+
return nil if !headers
|
127
137
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
138
|
+
while true
|
139
|
+
line = stream.get_line()
|
140
|
+
break if line.empty?
|
141
|
+
|
142
|
+
m = line.match(RE_HEADER_LINE)
|
143
|
+
raise "Invalid header" if !m
|
144
|
+
|
145
|
+
headers[m[1]] = m[2]
|
146
|
+
end
|
147
|
+
|
148
|
+
headers
|
133
149
|
end
|
134
150
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
151
|
+
def stream_get_request_line(stream)
|
152
|
+
line = stream.get_line()
|
153
|
+
|
154
|
+
m = line.match(RE_REQUEST_LINE)
|
155
|
+
return nil if !m
|
156
|
+
|
157
|
+
{
|
158
|
+
'method' => m[1].downcase,
|
159
|
+
'path' => m[2],
|
160
|
+
'protocol' => m[3].downcase
|
161
|
+
}
|
162
|
+
end
|
163
|
+
|
164
|
+
def parse_http_stream
|
165
|
+
rfd, wfd = UM.pipe
|
166
|
+
queue = UM::Queue.new
|
167
|
+
|
168
|
+
$machine.spin do
|
169
|
+
headers = stream_parse_headers(rfd)
|
170
|
+
$machine.push(queue, headers)
|
171
|
+
rescue Exception => e
|
172
|
+
p e
|
173
|
+
puts e.backtrace.join("\n")
|
174
|
+
exit!
|
175
|
+
end
|
176
|
+
|
177
|
+
$machine.write(wfd, HTTP_MSG)
|
178
|
+
$machine.shift(queue)
|
179
|
+
ensure
|
180
|
+
($machine.close(rfd) rescue nil) if rfd
|
181
|
+
($machine.close(wfd) rescue nil) if wfd
|
182
|
+
end
|
183
|
+
|
184
|
+
# 10000.times { parse_http_parser }
|
185
|
+
# 10000.times { parse_http_stringio }
|
186
|
+
# 10000.times { parse_http_stream }
|
187
|
+
# exit
|
188
|
+
|
189
|
+
# GC.disable
|
190
|
+
|
191
|
+
# OS = ObjectSpace
|
192
|
+
|
193
|
+
# def object_count
|
194
|
+
# counts = ObjectSpace.count_objects
|
195
|
+
# counts[:TOTAL] - counts[:FREE]
|
196
|
+
# end
|
197
|
+
|
198
|
+
# def alloc_count
|
199
|
+
# GC.start
|
200
|
+
# count0 = object_count
|
201
|
+
# yield
|
202
|
+
# count1 = object_count
|
203
|
+
# count1 - count0
|
204
|
+
# end
|
205
|
+
|
206
|
+
# X = 100
|
207
|
+
# p(
|
208
|
+
# alloc_http_parser: alloc_count { X.times { parse_http_parser } },
|
209
|
+
# alloc_stringio: alloc_count { X.times { parse_http_stringio } },
|
210
|
+
# alloc_stream: alloc_count { X.times { parse_http_stream } }
|
211
|
+
# )
|
212
|
+
# exit
|
141
213
|
|
142
214
|
Benchmark.ips do |x|
|
143
215
|
x.config(:time => 5, :warmup => 3)
|
144
216
|
|
145
217
|
x.report("http_parser") { parse_http_parser }
|
146
|
-
x.report("
|
218
|
+
x.report("stringio") { parse_http_stringio }
|
219
|
+
x.report("stream") { parse_http_stream }
|
147
220
|
|
148
221
|
x.compare!
|
149
222
|
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/inline'
|
4
|
+
|
5
|
+
gemfile do
|
6
|
+
source 'https://rubygems.org'
|
7
|
+
gem 'uringmachine', path: '..'
|
8
|
+
gem 'benchmark-ips'
|
9
|
+
end
|
10
|
+
|
11
|
+
require 'benchmark/ips'
|
12
|
+
require 'uringmachine'
|
13
|
+
|
14
|
+
def consume_from_queue(queue)
|
15
|
+
m = UM.new
|
16
|
+
while true
|
17
|
+
response_mailbox, closure = m.shift(queue)
|
18
|
+
result = closure.call
|
19
|
+
m.push(response_mailbox, result)
|
20
|
+
end
|
21
|
+
# rescue UM::Terminate
|
22
|
+
# # We can also add a timeout here
|
23
|
+
# t0 = Time.now
|
24
|
+
# while !queue.empty? && (Time.now - t0) < 10
|
25
|
+
# response_mailbox, closure = m.shift(queue)
|
26
|
+
# result = closure.call
|
27
|
+
# m.push(response_mailbox, result)
|
28
|
+
# end
|
29
|
+
end
|
30
|
+
|
31
|
+
N = 8
|
32
|
+
|
33
|
+
$machine = UM.new
|
34
|
+
@queue = UM::Queue.new
|
35
|
+
@threads = N.times.map { Thread.new { consume_from_queue(@queue) } }
|
36
|
+
|
37
|
+
def side_run(&block)
|
38
|
+
mailbox = Fiber.current.mailbox
|
39
|
+
$machine.push(@queue, [mailbox, block])
|
40
|
+
Thread.pass
|
41
|
+
$machine.shift(mailbox)
|
42
|
+
end
|
43
|
+
|
44
|
+
@rqueue = Queue.new
|
45
|
+
@rthreads = N.times.map { Thread.new { r_consume_from_queue(@rqueue) }}
|
46
|
+
|
47
|
+
def r_consume_from_queue(queue)
|
48
|
+
m = UM.new
|
49
|
+
while true
|
50
|
+
response_mailbox, closure = @rqueue.shift
|
51
|
+
result = closure.call
|
52
|
+
m.push(response_mailbox, result)
|
53
|
+
end
|
54
|
+
# rescue UM::Terminate
|
55
|
+
# # We can also add a timeout here
|
56
|
+
# t0 = Time.now
|
57
|
+
# while !queue.empty? && (Time.now - t0) < 10
|
58
|
+
# response_mailbox, closure = m.shift(queue)
|
59
|
+
# result = closure.call
|
60
|
+
# m.push(response_mailbox, result)
|
61
|
+
# end
|
62
|
+
end
|
63
|
+
|
64
|
+
def r_side_run(&block)
|
65
|
+
mailbox = Fiber.current.mailbox
|
66
|
+
@rqueue.push([mailbox, block])
|
67
|
+
Thread.pass
|
68
|
+
$machine.shift(mailbox)
|
69
|
+
end
|
70
|
+
|
71
|
+
# puts '*' * 40
|
72
|
+
# p r_side_run { }
|
73
|
+
# exit!
|
74
|
+
|
75
|
+
Benchmark.ips do |x|
|
76
|
+
x.config(:time => 5, :warmup => 2)
|
77
|
+
|
78
|
+
x.report("side-run") { side_run { } }
|
79
|
+
x.report("r-side-run") { r_side_run { } }
|
80
|
+
# x.report("snoozing") { $machine.snooze }
|
81
|
+
|
82
|
+
x.compare!
|
83
|
+
end
|
data/examples/bm_sqlite.rb
CHANGED
data/ext/um/um.c
CHANGED
@@ -356,6 +356,22 @@ inline VALUE um_read(struct um *machine, int fd, VALUE buffer, int maxlen, int b
|
|
356
356
|
return raise_if_exception(ret);
|
357
357
|
}
|
358
358
|
|
359
|
+
inline size_t um_read_raw(struct um *machine, int fd, char *buffer, int maxlen) {
|
360
|
+
struct um_op op;
|
361
|
+
um_prep_op(machine, &op, OP_READ);
|
362
|
+
struct io_uring_sqe *sqe = um_get_sqe(machine, &op);
|
363
|
+
io_uring_prep_read(sqe, fd, buffer, maxlen, -1);
|
364
|
+
|
365
|
+
VALUE ret = um_fiber_switch(machine);
|
366
|
+
if (um_check_completion(machine, &op)) {
|
367
|
+
return op.result.res;
|
368
|
+
|
369
|
+
}
|
370
|
+
|
371
|
+
raise_if_exception(ret);
|
372
|
+
return 0;
|
373
|
+
}
|
374
|
+
|
359
375
|
VALUE um_write(struct um *machine, int fd, VALUE str, int len) {
|
360
376
|
struct um_op op;
|
361
377
|
um_prep_op(machine, &op, OP_WRITE);
|
@@ -575,7 +591,7 @@ VALUE um_waitpid(struct um *machine, int pid, int options) {
|
|
575
591
|
struct io_uring_sqe *sqe = um_get_sqe(machine, &op);
|
576
592
|
|
577
593
|
siginfo_t infop;
|
578
|
-
io_uring_prep_waitid(sqe, P_PID, pid, &infop, options, 0);
|
594
|
+
io_uring_prep_waitid(sqe, pid == 0 ? P_ALL : P_PID, pid, &infop, options, 0);
|
579
595
|
|
580
596
|
VALUE ret = um_fiber_switch(machine);
|
581
597
|
if (um_check_completion(machine, &op))
|
data/ext/um/um.h
CHANGED
@@ -153,6 +153,24 @@ struct um_async_op {
|
|
153
153
|
struct um_op *op;
|
154
154
|
};
|
155
155
|
|
156
|
+
struct um_stream {
|
157
|
+
VALUE self;
|
158
|
+
|
159
|
+
struct um *machine;
|
160
|
+
int fd;
|
161
|
+
VALUE buffer;
|
162
|
+
ulong len;
|
163
|
+
ulong pos;
|
164
|
+
int eof;
|
165
|
+
};
|
166
|
+
|
167
|
+
struct um_write_buffer {
|
168
|
+
VALUE str;
|
169
|
+
size_t capa;
|
170
|
+
size_t len;
|
171
|
+
char *ptr;
|
172
|
+
};
|
173
|
+
|
156
174
|
extern VALUE cUM;
|
157
175
|
extern VALUE cMutex;
|
158
176
|
extern VALUE cQueue;
|
@@ -210,6 +228,7 @@ VALUE um_timeout(struct um *machine, VALUE interval, VALUE class);
|
|
210
228
|
VALUE um_sleep(struct um *machine, double duration);
|
211
229
|
VALUE um_periodically(struct um *machine, double interval);
|
212
230
|
VALUE um_read(struct um *machine, int fd, VALUE buffer, int maxlen, int buffer_offset);
|
231
|
+
size_t um_read_raw(struct um *machine, int fd, char *buffer, int maxlen);
|
213
232
|
VALUE um_read_each(struct um *machine, int fd, int bgid);
|
214
233
|
VALUE um_write(struct um *machine, int fd, VALUE str, int len);
|
215
234
|
VALUE um_close(struct um *machine, int fd);
|
@@ -251,6 +270,17 @@ VALUE um_queue_pop(struct um *machine, struct um_queue *queue);
|
|
251
270
|
VALUE um_queue_unshift(struct um *machine, struct um_queue *queue, VALUE value);
|
252
271
|
VALUE um_queue_shift(struct um *machine, struct um_queue *queue);
|
253
272
|
|
273
|
+
int stream_read_more(struct um_stream *stream);
|
274
|
+
VALUE stream_get_line(struct um_stream *stream);
|
275
|
+
VALUE stream_get_string(struct um_stream *stream, ulong len);
|
276
|
+
VALUE resp_get_line(struct um_stream *stream, VALUE out_buffer);
|
277
|
+
VALUE resp_get_string(struct um_stream *stream, ulong len, VALUE out_buffer);
|
278
|
+
VALUE resp_decode(struct um_stream *stream, VALUE out_buffer);
|
279
|
+
void resp_encode(struct um_write_buffer *buf, VALUE obj);
|
280
|
+
|
281
|
+
void write_buffer_init(struct um_write_buffer *buf, VALUE str);
|
282
|
+
void write_buffer_update_len(struct um_write_buffer *buf);
|
283
|
+
|
254
284
|
void um_define_net_constants(VALUE mod);
|
255
285
|
|
256
286
|
#endif // UM_H
|
data/ext/um/um_ext.c
CHANGED
@@ -3,6 +3,7 @@ void Init_Mutex();
|
|
3
3
|
void Init_Queue();
|
4
4
|
void Init_AsyncOp();
|
5
5
|
void Init_SSL();
|
6
|
+
void Init_Stream();
|
6
7
|
|
7
8
|
void Init_um_ext(void) {
|
8
9
|
Init_UM();
|
@@ -10,4 +11,5 @@ void Init_um_ext(void) {
|
|
10
11
|
Init_Queue();
|
11
12
|
Init_AsyncOp();
|
12
13
|
// Init_SSL();
|
14
|
+
Init_Stream();
|
13
15
|
}
|