uringmachine 0.30.0 → 0.31.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.
data/benchmark/openssl.rb CHANGED
@@ -24,54 +24,82 @@ Socket.do_not_reverse_lookup = true
24
24
  tcps = TCPServer.new("127.0.0.1", 0)
25
25
  port = tcps.connect_address.ip_port
26
26
 
27
- ssls = OpenSSL::SSL::SSLServer.new(tcps, ctx)
28
-
29
- Thread.new do
30
- Thread.current.report_on_exception = false
31
- loop do
32
- begin
33
- ssl = ssls.accept
34
- rescue OpenSSL::SSL::SSLError, IOError, Errno::EBADF, Errno::EINVAL,
35
- Errno::ECONNABORTED, Errno::ENOTSOCK, Errno::ECONNRESET
36
- retry
37
- end
38
-
39
- Thread.new do
40
- Thread.current.report_on_exception = false
27
+ pid = fork do
28
+ ssls = OpenSSL::SSL::SSLServer.new(tcps, ctx)
41
29
 
30
+ Thread.new do
31
+ Thread.current.report_on_exception = false
32
+ loop do
42
33
  begin
43
- while line = ssl.gets
44
- ssl.write(line)
34
+ ssl = ssls.accept
35
+ rescue OpenSSL::SSL::SSLError, IOError, Errno::EBADF, Errno::EINVAL,
36
+ Errno::ECONNABORTED, Errno::ENOTSOCK, Errno::ECONNRESET
37
+ retry
38
+ end
39
+
40
+ Thread.new do
41
+ Thread.current.report_on_exception = false
42
+
43
+ begin
44
+ while line = ssl.gets
45
+ ssl.write(line)
46
+ end
47
+ ensure
48
+ ssl.close
45
49
  end
46
- ensure
47
- ssl.close
50
+ true
48
51
  end
49
- true
50
52
  end
51
53
  end
54
+ sleep
55
+ rescue Interrupt
52
56
  end
53
57
 
54
- @ssl_stock = OpenSSL::SSL::SSLSocket.open("127.0.0.1", port)
58
+ at_exit {
59
+ Process.kill('SIGINT', pid)
60
+ Process.wait(pid)
61
+ }
62
+
63
+ begin
64
+ @ssl_stock = OpenSSL::SSL::SSLSocket.open("127.0.0.1", port)
65
+ rescue => e
66
+ p e
67
+ exit!
68
+ end
55
69
  @ssl_stock.sync_close = true
56
70
  @ssl_stock.connect
57
71
 
58
- um = UM.new
72
+ @um = UM.new
59
73
 
60
74
  @ssl_um = OpenSSL::SSL::SSLSocket.open("127.0.0.1", port)
61
75
  @ssl_um.sync_close = true
62
- um.ssl_set_bio(@ssl_um)
76
+ @um.ssl_set_bio(@ssl_um)
63
77
  @ssl_um.connect
64
78
 
79
+ @ssl_conn = OpenSSL::SSL::SSLSocket.open("127.0.0.1", port)
80
+ @ssl_conn.sync_close = true
81
+ @um.ssl_set_bio(@ssl_conn)
82
+ @ssl_conn.connect
83
+
84
+ @conn = @um.connection(@ssl_conn, :ssl)
85
+
65
86
  @msg = 'abc' * 1000
87
+ @msg_newline = @msg + "\n"
66
88
 
67
89
  def do_io(ssl)
68
90
  ssl.puts @msg
69
91
  ssl.gets
70
92
  end
71
93
 
94
+ def do_io_connection(ssl, um, conn)
95
+ um.ssl_write(ssl, @msg_newline, 0)
96
+ conn.read_line(0)
97
+ end
98
+
72
99
  Benchmark.ips do |x|
73
100
  x.report('stock') { do_io(@ssl_stock) }
74
101
  x.report('UM BIO') { do_io(@ssl_um) }
102
+ x.report('UM Stream') { do_io_connection(@ssl_conn, @um, @conn) }
75
103
 
76
104
  x.compare!(order: :baseline)
77
105
  end
@@ -78,7 +78,7 @@ buffers, to using managed buffers from the buffer pool.
78
78
  ```ruby
79
79
  machine.stream_recv(fd) do |stream|
80
80
  loop do
81
- line = stream.get_line(max: 60)
81
+ line = stream.read_line(max: 60)
82
82
  if (size = parse_size(line))
83
83
  data = stream.read(size)
84
84
  process_data(data)
@@ -0,0 +1,52 @@
1
+ @runqueue = []
2
+ @active_reads = {}; @active_timers = {}
3
+
4
+ def fiber_switch
5
+ while true
6
+ next_fiber, value = @runqueue.shift
7
+ return next_fiber.transfer value if next_fiber
8
+
9
+ process_events
10
+ end
11
+ end
12
+
13
+ def process_events
14
+ shortest_timeout = @active_timers.values.min - Time.now
15
+ process_reads(shortest_timeout)
16
+ now = Time.now
17
+ @active_timers.select { |_, t| t <= now }.keys.each {
18
+ @runqueue << it
19
+ @active_timers.delete(it)
20
+ }
21
+ end
22
+
23
+ def process_reads(timeout)
24
+ r, _ = IO.select(@active_reads.keys, [], [], timeout)
25
+ r&.each { |io|
26
+ @runqueue << [@active_reads[io], io.readpartial(256)]
27
+ @active_reads.delete(io)
28
+ }
29
+ end
30
+
31
+ def do_read(io)
32
+ @active_reads[io] = Fiber.current
33
+ fiber_switch
34
+ end
35
+
36
+ def do_sleep(time)
37
+ fiber = Fiber.current
38
+ @active_timers[fiber] = Time.now + time
39
+ fiber_switch
40
+ end
41
+
42
+ @runqueue << Fiber.new {
43
+ input = do_read(STDIN)
44
+ puts "Got: #{input}"
45
+ }
46
+
47
+ @runqueue << Fiber.new {
48
+ do_sleep(5)
49
+ puts "5 seconds have elapsed!"
50
+ }
51
+
52
+ fiber_switch
@@ -0,0 +1,26 @@
1
+ @fiber1 = Fiber.new {
2
+ count = 0
3
+ # read from STDIN
4
+ while true
5
+ count += 1
6
+ input = STDIN.read_nonblock(256, exception: false)
7
+ if input == :wait_readable
8
+ @fiber2.transfer
9
+ else
10
+ break
11
+ end
12
+ end
13
+ puts "Got: #{input} after #{count} tries"
14
+ }
15
+
16
+ @fiber2 = Fiber.new {
17
+ last = Time.now
18
+
19
+ # sleep
20
+ while Time.now < last + 5
21
+ @fiber1.transfer
22
+ end
23
+ STDOUT << "5 seconds have elapsed!\n"
24
+ }
25
+
26
+ @fiber1.transfer
@@ -0,0 +1,33 @@
1
+ @runqueue = []
2
+ def fiber_switch
3
+ next_fiber = @runqueue.shift
4
+ @runqueue << Fiber.current
5
+ next_fiber.transfer
6
+ end
7
+
8
+ @runqueue << Fiber.new {
9
+ count = 0
10
+ # read from STDIN
11
+ while true
12
+ count += 1
13
+ input = STDIN.read_nonblock(256, exception: false)
14
+ if input == :wait_readable
15
+ fiber_switch
16
+ else
17
+ break
18
+ end
19
+ end
20
+ puts "Got: #{input} after #{count} tries"
21
+ }
22
+
23
+ @runqueue << Fiber.new {
24
+ last = Time.now
25
+
26
+ # sleep
27
+ while Time.now < last + 10
28
+ fiber_switch
29
+ end
30
+ STDOUT << "10 seconds have elapsed!\n"
31
+ }
32
+
33
+ @runqueue.shift.transfer
@@ -0,0 +1,24 @@
1
+ #include <liburing.h>
2
+
3
+ struct io_uring ring;
4
+ struct io_uring_sqe *sqe;
5
+ struct io_uring_cqe *cqe;
6
+ int ret;
7
+ char buf[100];
8
+
9
+ ret = io_uring_queue_init(8, &ring, 0);
10
+ sqe = io_uring_get_sqe(&ring);
11
+ io_uring_prep_read(sqe, STDIN_FILENO, buf, 100, 0);
12
+ sqe->user_data = 42;
13
+ io_uring_submit(&ring);
14
+
15
+ ...
16
+
17
+ ret = io_uring_wait_cqe(&ring, &cqe);
18
+ if (!ret) {
19
+ if (cqe->user_data == 42) {
20
+ int len = cqe->res;
21
+ printf("Got: %d\n", len);
22
+ }
23
+ io_uring_cqe_seen(&ring, cqe);
24
+ }
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
- stream = UM::Stream.new($machine, fd)
69
+ conn = UM::Connection.new($machine, fd)
70
70
 
71
- while (l = stream.gets)
71
+ while (l = conn.gets)
72
72
  $machine.write(fd, "You said: #{l}")
73
73
  end
74
74
  rescue Exception => e
data/examples/stream.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
- stream = UM::Stream.new($machine, fd)
69
+ conn = UM::Stream.new($machine, fd)
70
70
 
71
- while (l = stream.gets)
71
+ while (l = conn.gets)
72
72
  $machine.write(fd, "You said: #{l}")
73
73
  end
74
74
  rescue Exception => e
data/ext/um/um.c CHANGED
@@ -652,11 +652,11 @@ VALUE um_write(struct um *machine, int fd, VALUE buffer, size_t len, __u64 file_
652
652
  return ret;
653
653
  }
654
654
 
655
- size_t um_write_raw(struct um *machine, int fd, const char *buffer, size_t maxlen) {
655
+ size_t um_write_raw(struct um *machine, int fd, const char *buffer, size_t len) {
656
656
  struct um_op *op = um_op_acquire(machine);
657
657
  um_prep_op(machine, op, OP_WRITE, 2, 0);
658
658
  struct io_uring_sqe *sqe = um_get_sqe(machine, op);
659
- io_uring_prep_write(sqe, fd, buffer, maxlen, 0);
659
+ io_uring_prep_write(sqe, fd, buffer, len, 0);
660
660
 
661
661
  int res = 0;
662
662
  VALUE ret = um_yield(machine);
@@ -831,6 +831,23 @@ VALUE um_send(struct um *machine, int fd, VALUE buffer, size_t len, int flags) {
831
831
  return ret;
832
832
  }
833
833
 
834
+ size_t um_send_raw(struct um *machine, int fd, const char *buffer, size_t len, int flags) {
835
+ struct um_op *op = um_op_acquire(machine);
836
+ um_prep_op(machine, op, OP_SEND, 2, 0);
837
+ struct io_uring_sqe *sqe = um_get_sqe(machine, op);
838
+ io_uring_prep_send(sqe, fd, buffer, len, flags);
839
+
840
+ int res = 0;
841
+ VALUE ret = um_yield(machine);
842
+
843
+ if (likely(um_verify_op_completion(machine, op, true))) res = op->result.res;
844
+ um_op_release(machine, op);
845
+
846
+ RAISE_IF_EXCEPTION(ret);
847
+ RB_GC_GUARD(ret);
848
+ return res;
849
+ }
850
+
834
851
  // for some reason we don't get this define from liburing/io_uring.h
835
852
  #define IORING_SEND_VECTORIZED (1U << 5)
836
853
 
@@ -1478,7 +1495,7 @@ int read_recv_each_multishot_process_result(struct op_ctx *ctx, struct um_op_res
1478
1495
  return false;
1479
1496
 
1480
1497
  *total += result->res;
1481
- VALUE buf = um_get_string_from_buffer_ring(ctx->machine, ctx->bgid, result->res, result->flags);
1498
+ VALUE buf = um_read_from_buffer_ring(ctx->machine, ctx->bgid, result->res, result->flags);
1482
1499
  rb_yield(buf);
1483
1500
  RB_GC_GUARD(buf);
1484
1501
 
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 um_stream_mode {
84
- STREAM_BP_READ,
85
- STREAM_BP_RECV,
86
- STREAM_SSL,
87
- STREAM_STRING,
88
- STREAM_IO_BUFFER
83
+ enum um_connection_mode {
84
+ CONNECTION_FD,
85
+ CONNECTION_SOCKET,
86
+ CONNECTION_SSL,
87
+ CONNECTION_STRING,
88
+ CONNECTION_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 um_stream {
275
+ struct um_connection {
276
276
  VALUE self;
277
277
  struct um *machine;
278
278
 
279
- enum um_stream_mode mode;
279
+ enum um_connection_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 eStreamRESPError;
307
+ extern VALUE eConnectionRESPError;
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);
@@ -352,7 +352,7 @@ int um_get_buffer_bytes_for_writing(VALUE buffer, const void **base, size_t *siz
352
352
  void * um_prepare_read_buffer(VALUE buffer, ssize_t len, ssize_t ofs);
353
353
  void um_update_read_buffer(VALUE buffer, ssize_t buffer_offset, __s32 result);
354
354
  int um_setup_buffer_ring(struct um *machine, unsigned size, unsigned count);
355
- VALUE um_get_string_from_buffer_ring(struct um *machine, int bgid, __s32 result, __u32 flags);
355
+ VALUE um_read_from_buffer_ring(struct um *machine, int bgid, __s32 result, __u32 flags);
356
356
  void um_add_strings_to_buffer_ring(struct um *machine, int bgid, VALUE strings);
357
357
  struct iovec *um_alloc_iovecs_for_writing(int argc, VALUE *argv, size_t *total_len);
358
358
  void um_advance_iovecs_for_writing(struct iovec **ptr, int *len, size_t adv);
@@ -378,7 +378,7 @@ VALUE um_read(struct um *machine, int fd, VALUE buffer, size_t maxlen, ssize_t b
378
378
  size_t um_read_raw(struct um *machine, int fd, char *buffer, size_t maxlen);
379
379
  VALUE um_read_each(struct um *machine, int fd, int bgid);
380
380
  VALUE um_write(struct um *machine, int fd, VALUE buffer, size_t len, __u64 file_offset);
381
- size_t um_write_raw(struct um *machine, int fd, const char *buffer, size_t maxlen);
381
+ size_t um_write_raw(struct um *machine, int fd, const char *buffer, size_t len);
382
382
  VALUE um_writev(struct um *machine, int fd, int argc, VALUE *argv);
383
383
  VALUE um_write_async(struct um *machine, int fd, VALUE buffer, size_t len, __u64 file_offset);
384
384
  VALUE um_close(struct um *machine, int fd);
@@ -403,6 +403,7 @@ VALUE um_accept_into_queue(struct um *machine, int fd, VALUE queue);
403
403
  VALUE um_socket(struct um *machine, int domain, int type, int protocol, uint flags);
404
404
  VALUE um_connect(struct um *machine, int fd, const struct sockaddr *addr, socklen_t addrlen);
405
405
  VALUE um_send(struct um *machine, int fd, VALUE buffer, size_t len, int flags);
406
+ size_t um_send_raw(struct um *machine, int fd, const char *buffer, size_t len, int flags);
406
407
  VALUE um_sendv(struct um *machine, int fd, int argc, VALUE *argv);
407
408
  VALUE um_send_bundle(struct um *machine, int fd, int bgid, VALUE strings);
408
409
  VALUE um_recv(struct um *machine, int fd, VALUE buffer, size_t maxlen, int flags);
@@ -437,13 +438,16 @@ VALUE um_queue_pop(struct um *machine, struct um_queue *queue);
437
438
  VALUE um_queue_unshift(struct um *machine, struct um_queue *queue, VALUE value);
438
439
  VALUE um_queue_shift(struct um *machine, struct um_queue *queue);
439
440
 
440
- void stream_teardown(struct um_stream *stream);
441
- void stream_clear(struct um_stream *stream);
442
- VALUE stream_get_line(struct um_stream *stream, VALUE buf, size_t maxlen);
443
- VALUE stream_get_string(struct um_stream *stream, VALUE out_buffer, ssize_t len, size_t inc, int safe_inc);
444
- void stream_skip(struct um_stream *stream, size_t inc, int safe_inc);
445
- void stream_each(struct um_stream *stream);
446
- VALUE resp_decode(struct um_stream *stream, VALUE out_buffer);
441
+ void connection_teardown(struct um_connection *conn);
442
+ void connection_clear(struct um_connection *conn);
443
+ VALUE connection_read_line(struct um_connection *conn, VALUE out_buffer, size_t maxlen);
444
+ VALUE connection_read(struct um_connection *conn, VALUE out_buffer, ssize_t len, size_t inc, int safe_inc);
445
+ VALUE connection_read_to_delim(struct um_connection *conn, VALUE out_buffer, VALUE delim, ssize_t maxlen);
446
+ void connection_skip(struct um_connection *conn, size_t inc, int safe_inc);
447
+ void connection_read_each(struct um_connection *conn);
448
+ size_t connection_write_raw(struct um_connection *conn, const char *buffer, size_t len);
449
+ VALUE connection_writev(struct um_connection *conn, int argc, VALUE *argv);
450
+ VALUE resp_read(struct um_connection *conn, VALUE out_buffer);
447
451
  void resp_encode(struct um_write_buffer *buf, VALUE obj);
448
452
  void resp_encode_cmd(struct um_write_buffer *buf, int argc, VALUE *argv);
449
453
 
@@ -463,6 +467,8 @@ void um_ssl_set_bio(struct um *machine, VALUE ssl_obj);
463
467
  int um_ssl_read(struct um *machine, VALUE ssl, VALUE buf, size_t maxlen);
464
468
  int um_ssl_read_raw(struct um *machine, VALUE ssl_obj, char *ptr, size_t maxlen);
465
469
  int um_ssl_write(struct um *machine, VALUE ssl, VALUE buf, size_t len);
470
+ int um_ssl_write_raw(struct um *machine, VALUE ssl, const char *buffer, size_t len);
471
+ int um_ssl_writev(struct um *machine, VALUE ssl, int argc, VALUE *argv);
466
472
 
467
473
  void bp_setup(struct um *machine);
468
474
  void bp_teardown(struct um *machine);