evt 0.3.6 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d7c2d7880e0a6e8232a91b2aa154adcc7705c87d3907b33beb27f3f7b10dcbac
4
- data.tar.gz: 7d882336538396f34a3c54bb8ccc3dd34b9431f60709d9527c87e3136d0c646b
3
+ metadata.gz: 3275dc2e231b57c3e740671f2d431ede41ca23339ba799b280edeed1c7be8d2c
4
+ data.tar.gz: 4107ecb57ec3ff7e566187013348a056773ac654eb2b369b7fa8bb057675750e
5
5
  SHA512:
6
- metadata.gz: 28f8fb3d3ed2b0c1ee797ba1a36974392e5e7d8c00b38c4f7b25f95c0bf759e2d7f20402f6cb7dc1399187cc4c03e7c0e8d80d641551cc815e20db992d014843
7
- data.tar.gz: 90e7cb4395e297761462376990b5faef42598d517dcbc3d5b0001e08d5e39582d158739ba5461eb3700651166fb1041ab15b551dd50f1af002116abc3698cea9
6
+ metadata.gz: db3172fe0ee6776480a64ee036aedb03b09ee5d5c8a5088fe68e4a969d7058964e8c55b004bb69962f61bffdb13a1c6c28ce49d339f8194e616ae44d877a9616
7
+ data.tar.gz: 94e287ddb35ae5f99e15ebf27ef76ce54ce3272008fe7c535483706111a8a39ff3168d2289135a027934d45c4382b51527c240fc9d7fbf6b9ce13f2ca7b016e3
data/README.md CHANGED
@@ -19,30 +19,59 @@ The Event Library that designed for Ruby 3.0 Fiber Scheduler.
19
19
  | epoll | ✅ (See 2) | ❌ | ❌ | ❌ |
20
20
  | kqueue | ❌ | ❌ | ✅ (⚠️ See 5) | ✅ |
21
21
  | IOCP | ❌ | ❌ (⚠️See 3) | ❌ | ❌ |
22
- | Ruby (`IO.select`) | ✅ Fallback | ✅ (⚠️See 4) | ✅ Fallback | ✅ Fallback |
22
+ | Ruby (`IO.select`) | ✅ (See 6) | ✅ (⚠️See 4) | ✅ (See 6) | ✅ (See 6) |
23
23
 
24
24
  1. when liburing is installed. (Currently fixing)
25
25
  2. when kernel version >= 2.6.9
26
26
  3. WOULD NOT WORK until `FILE_FLAG_OVERLAPPED` is included in I/O initialization process.
27
- 4. Some I/Os are not able to be nonblock under Windows. See [Scheduler Docs](https://docs.ruby-lang.org/en/master/doc/scheduler_md.html#label-IO).
27
+ 4. Some I/Os are not able to be nonblock under Windows. Using POSIX select, **SLOW**. See [Scheduler Docs](https://docs.ruby-lang.org/en/master/doc/scheduler_md.html#label-IO).
28
28
  5. `kqueue` performance in Darwin is very poor. **MAY BE DISABLED IN THE FUTURE.**
29
+ 6. Using poll
29
30
 
30
31
  ### Benchmark
31
32
 
32
- The benchmark is running under `v0.3.1` version. See `example.rb` in [midori](https://github.com/midori-rb/midori.rb) for test code, the test is running under a single-thread server.
33
+ The benchmark is running under `v0.3.6` version. See `example.rb` in [midori](https://github.com/midori-rb/midori.rb) for test code, the test is running under a single-thread server.
33
34
 
34
- The test command is `wrk -t4 -c8192 -d30s http://localhost:3001`.
35
+ The test command is `wrk -t4 -c8192 -d30s http://localhost:8080`.
35
36
 
36
37
  All of the systems have set their file descriptor limit to maximum.
37
38
  On systems raising "Fiber unable to allocate memory", `sudo sysctl -w vm.max_map_count=1000000` is set.
38
39
 
39
40
  | OS | CPU | Memory | Backend | req/s |
40
- | ----- | ----------- | ------ | ---------------------- | --------------|
41
- | Linux | Ryzen 2700x | 64GB | epoll | 1853259.47 |
41
+ | ----- | ----------- | ------ | ---------------------- | ------------- |
42
+ | Linux | Ryzen 2700x | 64GB | epoll | 2035742.59 |
42
43
  | Linux | Ryzen 2700x | 64GB | io_uring | require fixes |
43
- | Linux | Ryzen 2700x | 64GB | IO.select (using poll) | 1636849.15 |
44
- | macOS | i7-6820HQ | 16GB | kqueue | 247370.37 |
45
- | macOS | i7-6820HQ | 16GB | IO.select (using poll) | 323391.38 |
44
+ | Linux | Ryzen 2700x | 64GB | IO.select (using poll) | 1837640.54 |
45
+ | macOS | i7-6820HQ | 16GB | kqueue | 257821.78 |
46
+ | macOS | i7-6820HQ | 16GB | IO.select (using poll) | 338392.12 |
47
+
48
+ We also test the server with Redis request, with a [monkey-patched redis library](https://github.com/midori-rb/midori-contrib/blob/master/lib/midori-contrib/redic.rb). The example code is following:
49
+
50
+ ```ruby
51
+ require 'evt'
52
+ require 'midori'
53
+ require 'midori-contrib/redic'
54
+
55
+ Fiber.set_scheduler Evt::Scheduler.new
56
+ REDIS = Redic.new
57
+
58
+ class HelloWorldAPI < Midori::API
59
+ get '/' do
60
+ REDIS.call 'GET', 'foo'
61
+ end
62
+ end
63
+
64
+ Fiber.schedule do
65
+ Midori::Runner.new(HelloWorldAPI).start
66
+ end
67
+ ```
68
+
69
+ The benckmark result is as following:
70
+
71
+ | OS | CPU | Memory | Backend | req/s |
72
+ | ----- | ----------- | ------ | ------- | --------- |
73
+ | Linux | Ryzen 2700x | 64GB | epoll | 378060.30 |
74
+ | macOS | i7-6820HQ | 16GB | kqueue | 204460.32 |
46
75
 
47
76
  ## Install
48
77
 
@@ -74,6 +103,15 @@ end
74
103
  # "Hello World"
75
104
  ```
76
105
 
106
+ | | Windows `WaitFor...` | Windows `select` | Windows IOCP | `io_uring` | `epoll` | `kqueue` | `poll` | *NIX `select` |
107
+ | -------------- | -------------------- | ---------------- | ------------ | ---------- | ------- | -------- | ------ | ------------- |
108
+ | Anonymous Pipe | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
109
+ | Named Pipe | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
110
+ | Socket | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
111
+ | File | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
112
+
113
+
114
+
77
115
  ## Roadmap
78
116
 
79
117
  - [x] Support epoll/kqueue/select
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
  spec.description = "A low-level Event Handler designed for Ruby 3 Scheduler for better performance"
11
11
  spec.homepage = "https://github.com/dsh0416/evt"
12
12
  spec.license = 'BSD-3-Clause'
13
- spec.required_ruby_version = '>= 3.0.0.rc1'
13
+ spec.required_ruby_version = '>= 3.0.0'
14
14
 
15
15
  spec.metadata["homepage_uri"] = spec.homepage
16
16
  spec.metadata["source_code_uri"] = "https://github.com/dsh0416/evt"
@@ -26,6 +26,8 @@ VALUE method_scheduler_epoll_register(VALUE self, VALUE io, VALUE interest) {
26
26
  event.events |= EPOLLOUT;
27
27
  }
28
28
 
29
+ event.events |= EPOLLRDHUP;
30
+
29
31
  event.data.ptr = (void*) io;
30
32
 
31
33
  epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event);
@@ -34,14 +36,13 @@ VALUE method_scheduler_epoll_register(VALUE self, VALUE io, VALUE interest) {
34
36
 
35
37
  VALUE method_scheduler_epoll_wait(VALUE self) {
36
38
  int n, epfd, i, event_flag, timeout;
37
- VALUE next_timeout, obj_io, readables, writables, result;
39
+ VALUE next_timeout, obj_io, iovs, result;
38
40
  ID id_next_timeout = rb_intern("next_timeout");
39
41
  ID id_push = rb_intern("push");
40
42
 
41
43
  epfd = NUM2INT(rb_iv_get(self, "@epfd"));
42
44
  next_timeout = rb_funcall(self, id_next_timeout, 0);
43
- readables = rb_ary_new();
44
- writables = rb_ary_new();
45
+ iovs = rb_ary_new();
45
46
 
46
47
  if (next_timeout == Qnil) {
47
48
  timeout = -1;
@@ -58,20 +59,17 @@ VALUE method_scheduler_epoll_wait(VALUE self) {
58
59
 
59
60
  for (i = 0; i < n; i++) {
60
61
  event_flag = events[i].events;
61
- if (event_flag & EPOLLIN) {
62
- obj_io = (VALUE) events[i].data.ptr;
63
- rb_funcall(readables, id_push, 1, obj_io);
64
- }
65
-
66
- if (event_flag & EPOLLOUT) {
67
- obj_io = (VALUE) events[i].data.ptr;
68
- rb_funcall(writables, id_push, 1, obj_io);
69
- }
62
+ obj_io = (VALUE) events[i].data.ptr;
63
+ VALUE e = rb_ary_new2(2);
64
+ rb_ary_store(e, 0, obj_io);
65
+ rb_ary_store(e, 1, INT2NUM(event_flag));
66
+ rb_funcall(iovs, id_push, 1, e);
70
67
  }
71
68
 
72
- result = rb_ary_new2(2);
73
- rb_ary_store(result, 0, readables);
74
- rb_ary_store(result, 1, writables);
69
+ result = rb_ary_new2(3);
70
+ rb_ary_store(result, 0, rb_ary_new());
71
+ rb_ary_store(result, 1, rb_ary_new());
72
+ rb_ary_store(result, 2, iovs);
75
73
  return result;
76
74
  }
77
75
 
@@ -21,6 +21,56 @@ class Evt::Epoll < Evt::Bundled
21
21
  epoll_deregister(io)
22
22
  end
23
23
 
24
+ def io_wait(io, events, duration)
25
+ @iovs[io] = Fiber.current
26
+ self.register(io, events)
27
+ Fiber.yield
28
+ self.deregister(io)
29
+ true
30
+ end
31
+
32
+ # def io_read(io, buffer, offset, length)
33
+ # result = +('')
34
+
35
+ # self.register(io, IO::READABLE)
36
+ # direct_read = io.read_nonblock(length, exception: false)
37
+
38
+ # unless direct_read == :wait_readable
39
+ # result << direct_read
40
+ # end
41
+
42
+ # until result.length >= length or io.closed? or io.eof?
43
+ # @iovs[io] = Fiber.current
44
+ # Fiber.yield
45
+ # todo = length - result.length
46
+ # result << io.read_nonblock(todo)
47
+ # end
48
+
49
+ # self.deregister(io)
50
+ # buffer[offset...offset+result.length] = result
51
+ # result.length
52
+ # end
53
+
54
+ # def io_write(io, buffer, offset, length)
55
+ # finished = 0
56
+
57
+ # self.register(io, IO::WRITABLE)
58
+ # direct_write = io.write_nonblock(buffer.byteslice(offset+finished..-1), exception: false)
59
+ # unless direct_write == :wait_writable
60
+ # finished += direct_write
61
+ # end
62
+
63
+ # until finished >= length or io.closed?
64
+ # @iovs[io] = Fiber.current
65
+ # Fiber.yield
66
+ # finished += io.write_nonblock(buffer.byteslice(offset+finished..-1))
67
+ # end
68
+
69
+ # self.deregister(io)
70
+
71
+ # finished
72
+ # end
73
+
24
74
  def wait
25
75
  epoll_wait
26
76
  end
@@ -22,6 +22,9 @@ class Evt::Select < Evt::Bundled
22
22
 
23
23
  def wait
24
24
  select_wait
25
+ rescue IOError => _
26
+ collect(true)
27
+ return [], []
25
28
  rescue Errno::EBADF => _
26
29
  collect(true)
27
30
  return [], []
@@ -20,13 +20,14 @@ class Evt::Uring < Evt::Bundled
20
20
  def deregister(io)
21
21
  end
22
22
 
23
- def io_read(io, buffer, offset, length)
24
- uring_io_read(io, buffer, offset, length)
25
- end
26
-
27
- def io_write(io, buffer, offset, length)
28
- uring_io_write(io, buffer, offset, length)
29
- end
23
+ # Disable direct I/Os for now
24
+ # def io_read(io, buffer, offset, length)
25
+ # uring_io_read(io, buffer, offset, length)
26
+ # end
27
+
28
+ # def io_write(io, buffer, offset, length)
29
+ # uring_io_write(io, buffer, offset, length)
30
+ # end
30
31
 
31
32
  def wait
32
33
  uring_wait
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Evt
4
- VERSION = "0.3.6"
4
+ VERSION = "0.4.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: evt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.6
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Delton Ding
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-12-23 00:00:00.000000000 Z
11
+ date: 2020-12-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -100,14 +100,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - ">="
102
102
  - !ruby/object:Gem::Version
103
- version: 3.0.0.rc1
103
+ version: 3.0.0
104
104
  required_rubygems_version: !ruby/object:Gem::Requirement
105
105
  requirements:
106
106
  - - ">="
107
107
  - !ruby/object:Gem::Version
108
108
  version: '0'
109
109
  requirements: []
110
- rubygems_version: 3.2.2
110
+ rubygems_version: 3.2.3
111
111
  signing_key:
112
112
  specification_version: 4
113
113
  summary: The Event Library that designed for Ruby 3.0 Fiber Scheluer.