uringmachine 0.19.1 → 0.21.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/.github/workflows/test.yml +3 -4
- data/CHANGELOG.md +32 -1
- data/TODO.md +0 -39
- data/examples/bm_fileno.rb +33 -0
- data/examples/bm_mutex.rb +85 -0
- data/examples/bm_mutex_single.rb +33 -0
- data/examples/bm_queue.rb +29 -29
- data/examples/bm_send.rb +2 -5
- data/examples/bm_snooze.rb +20 -42
- data/examples/bm_write.rb +4 -1
- data/examples/fiber_scheduler_demo.rb +15 -51
- data/examples/fiber_scheduler_fork.rb +24 -0
- data/examples/nc_ssl.rb +71 -0
- data/ext/um/extconf.rb +5 -15
- data/ext/um/um.c +310 -74
- data/ext/um/um.h +66 -29
- data/ext/um/um_async_op.c +1 -1
- data/ext/um/um_async_op_class.c +2 -2
- data/ext/um/um_buffer.c +1 -1
- data/ext/um/um_class.c +178 -31
- data/ext/um/um_const.c +51 -3
- data/ext/um/um_mutex_class.c +1 -1
- data/ext/um/um_op.c +37 -0
- data/ext/um/um_queue_class.c +1 -1
- data/ext/um/um_stream.c +5 -5
- data/ext/um/um_stream_class.c +3 -0
- data/ext/um/um_sync.c +28 -39
- data/ext/um/um_utils.c +59 -19
- data/grant-2025/journal.md +353 -0
- data/grant-2025/tasks.md +135 -0
- data/lib/uringmachine/fiber_scheduler.rb +316 -57
- data/lib/uringmachine/version.rb +1 -1
- data/lib/uringmachine.rb +6 -0
- data/test/test_fiber_scheduler.rb +640 -0
- data/test/test_stream.rb +2 -2
- data/test/test_um.rb +722 -54
- data/uringmachine.gemspec +5 -5
- data/vendor/liburing/.github/workflows/ci.yml +94 -1
- data/vendor/liburing/.github/workflows/test_build.c +9 -0
- data/vendor/liburing/configure +27 -0
- data/vendor/liburing/examples/Makefile +6 -0
- data/vendor/liburing/examples/helpers.c +8 -0
- data/vendor/liburing/examples/helpers.h +5 -0
- data/vendor/liburing/liburing.spec +1 -1
- data/vendor/liburing/src/Makefile +9 -3
- data/vendor/liburing/src/include/liburing/barrier.h +11 -5
- data/vendor/liburing/src/include/liburing/io_uring/query.h +41 -0
- data/vendor/liburing/src/include/liburing/io_uring.h +51 -0
- data/vendor/liburing/src/include/liburing/sanitize.h +16 -4
- data/vendor/liburing/src/include/liburing.h +458 -121
- data/vendor/liburing/src/liburing-ffi.map +16 -0
- data/vendor/liburing/src/liburing.map +8 -0
- data/vendor/liburing/src/sanitize.c +4 -1
- data/vendor/liburing/src/setup.c +7 -4
- data/vendor/liburing/test/232c93d07b74.c +4 -16
- data/vendor/liburing/test/Makefile +15 -1
- data/vendor/liburing/test/accept.c +2 -13
- data/vendor/liburing/test/bind-listen.c +175 -13
- data/vendor/liburing/test/conn-unreach.c +132 -0
- data/vendor/liburing/test/fd-pass.c +32 -7
- data/vendor/liburing/test/fdinfo.c +39 -12
- data/vendor/liburing/test/fifo-futex-poll.c +114 -0
- data/vendor/liburing/test/fifo-nonblock-read.c +1 -12
- data/vendor/liburing/test/futex.c +1 -1
- data/vendor/liburing/test/helpers.c +99 -2
- data/vendor/liburing/test/helpers.h +9 -0
- data/vendor/liburing/test/io_uring_passthrough.c +6 -12
- data/vendor/liburing/test/mock_file.c +379 -0
- data/vendor/liburing/test/mock_file.h +47 -0
- data/vendor/liburing/test/nop.c +2 -2
- data/vendor/liburing/test/nop32-overflow.c +150 -0
- data/vendor/liburing/test/nop32.c +126 -0
- data/vendor/liburing/test/pipe.c +166 -0
- data/vendor/liburing/test/poll-race-mshot.c +13 -1
- data/vendor/liburing/test/read-write.c +4 -4
- data/vendor/liburing/test/recv-mshot-fair.c +81 -34
- data/vendor/liburing/test/recvsend_bundle.c +1 -1
- data/vendor/liburing/test/resize-rings.c +2 -0
- data/vendor/liburing/test/ring-query.c +322 -0
- data/vendor/liburing/test/ringbuf-loop.c +87 -0
- data/vendor/liburing/test/ringbuf-read.c +4 -4
- data/vendor/liburing/test/runtests.sh +2 -2
- data/vendor/liburing/test/send-zerocopy.c +43 -5
- data/vendor/liburing/test/send_recv.c +103 -32
- data/vendor/liburing/test/shutdown.c +2 -12
- data/vendor/liburing/test/socket-nb.c +3 -14
- data/vendor/liburing/test/socket-rw-eagain.c +2 -12
- data/vendor/liburing/test/socket-rw-offset.c +2 -12
- data/vendor/liburing/test/socket-rw.c +2 -12
- data/vendor/liburing/test/sqe-mixed-bad-wrap.c +87 -0
- data/vendor/liburing/test/sqe-mixed-nop.c +82 -0
- data/vendor/liburing/test/sqe-mixed-uring_cmd.c +153 -0
- data/vendor/liburing/test/timestamp.c +56 -19
- data/vendor/liburing/test/vec-regbuf.c +2 -4
- data/vendor/liburing/test/wq-aff.c +7 -0
- metadata +37 -15
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e14941110d09a575728da68cb038a02334d151f0d384d88ad67a34b21a49d234
|
|
4
|
+
data.tar.gz: 158299106b117a973163ae480ea4e9827a0cb88eb76b2323da04fd631e8916ca
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f71a5b6b6740fea281df8880511b424a0c759e876e17f79a6b661453416d13c2d9d65e0c53ddee5df066ca92472571ffae8c0e9a4ca4fd745d02705a8645965d
|
|
7
|
+
data.tar.gz: baa86b9bc0009c69bfe894aae3489d43ed28d1fca44a24a9ddc7cc1625a54de6c17f65731c1a707af561942174f9584554a183a67f8428d5855e799c274db0b6
|
data/.github/workflows/test.yml
CHANGED
|
@@ -11,9 +11,8 @@ jobs:
|
|
|
11
11
|
strategy:
|
|
12
12
|
fail-fast: false
|
|
13
13
|
matrix:
|
|
14
|
-
# macos-latest uses arm64, macos-13 uses x86
|
|
15
14
|
os: [ubuntu-latest]
|
|
16
|
-
ruby: ['
|
|
15
|
+
ruby: ['head']
|
|
17
16
|
|
|
18
17
|
name: ${{matrix.os}}, ${{matrix.ruby}}
|
|
19
18
|
|
|
@@ -32,5 +31,5 @@ jobs:
|
|
|
32
31
|
- name: Compile C-extension
|
|
33
32
|
run: bundle exec rake compile
|
|
34
33
|
- name: Run tests
|
|
35
|
-
|
|
36
|
-
run: bundle exec rake test
|
|
34
|
+
run: bundle exec ruby test/run.rb --verbose
|
|
35
|
+
# run: bundle exec rake test
|
data/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,35 @@
|
|
|
1
|
-
# 0.
|
|
1
|
+
# 0.21.0 2025-12-06
|
|
2
|
+
|
|
3
|
+
- Add `UM#submit`
|
|
4
|
+
- Update liburing
|
|
5
|
+
- Do not release GVL in um_submit if SQ does not need entering the kernel
|
|
6
|
+
- Fix compilation when rb_process_status_new is not available
|
|
7
|
+
- Fix um_futex_wake_transient to submit SQE, fix futex_wait usage
|
|
8
|
+
- Add debug logging for key io_uring interactions
|
|
9
|
+
- Add UM#mark and DEBUG_MARK for debugging specific UM instances
|
|
10
|
+
- Short-circuit zero-length writes
|
|
11
|
+
- Add optional file_offset argument to #read, #write. Add optional len and file_off
|
|
12
|
+
set arguments to #write_async
|
|
13
|
+
- Add support for specifying SQPOLL mode and SQ idle timeout in `UM#initialize`
|
|
14
|
+
- Add support for specifying number of SQ entries in `UM#initialize`
|
|
15
|
+
- Implement global worker pool for blocking operations in fiber scheduler
|
|
16
|
+
- Finish implementing all fiber scheduler hooks
|
|
17
|
+
- Add `UM#select`
|
|
18
|
+
- Add `UM#wakeup`
|
|
19
|
+
- Add `UM#total_op_count`
|
|
20
|
+
|
|
21
|
+
# 0.20.0 2025-11-26
|
|
22
|
+
|
|
23
|
+
- Add `UM.pidfd_open`, `UM.pidfd_send_signal` methods
|
|
24
|
+
- Add `#waitid`, `#waitid_status` methods, remove `#waitpid`
|
|
25
|
+
- Set minimal kernel version to 6.7
|
|
26
|
+
- Add `UM::Error` exception class
|
|
27
|
+
- Add support for `IO::Buffer` in all I/O methods
|
|
28
|
+
- Fix and improve mutex and queue implementations
|
|
29
|
+
- Add UM.debug method
|
|
30
|
+
- Implement Fiber scheduler (WIP)
|
|
31
|
+
|
|
32
|
+
# 0.19.1 2025-11-03
|
|
2
33
|
|
|
3
34
|
- Add `RB_GC_GUARD` in `process_runqueue_op`
|
|
4
35
|
|
data/TODO.md
CHANGED
|
@@ -1,44 +1,5 @@
|
|
|
1
1
|
## immediate
|
|
2
2
|
|
|
3
|
-
- make a reproducer for segfault on timeout, spin lots of fibers where a timeout
|
|
4
|
-
wraps a #shift call (from an empty queue).
|
|
5
|
-
- see also: https://mensfeld.pl/2025/11/ruby-ffi-gc-bug-hash-becomes-string/
|
|
6
|
-
|
|
7
|
-
Analysis:
|
|
8
|
-
|
|
9
|
-
- The segfault is related to timeouts
|
|
10
|
-
- Looking at process_runqueue_op (um.c):
|
|
11
|
-
|
|
12
|
-
```c
|
|
13
|
-
inline VALUE process_runqueue_op(struct um *machine, struct um_op *op) {
|
|
14
|
-
VALUE fiber = op->fiber;
|
|
15
|
-
VALUE value = op->value;
|
|
16
|
-
|
|
17
|
-
// on timeout, the op flags are changed to turn on OP_F_TRANSIENT
|
|
18
|
-
if (unlikely(op->flags & OP_F_TRANSIENT))
|
|
19
|
-
// here the op is freed, so the value is not visible to the GC anymoore
|
|
20
|
-
um_op_free(machine, op);
|
|
21
|
-
|
|
22
|
-
// if a GC occurs here, we risk a segfault
|
|
23
|
-
|
|
24
|
-
// value is used
|
|
25
|
-
return rb_fiber_transfer(fiber, 1, &value);
|
|
26
|
-
}
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
- So, a possible solution is to put a `RB_GC_GUARD` after the `return`.
|
|
30
|
-
- But first, I want to be able to reproduce it. We can start by setting
|
|
31
|
-
`GC.stress = true` on tests and see if we segfault.
|
|
32
|
-
|
|
33
|
-
## FiberScheduler implementation
|
|
34
|
-
|
|
35
|
-
Some resources:
|
|
36
|
-
|
|
37
|
-
- https://github.com/socketry/async/blob/main/context/getting-started.md
|
|
38
|
-
- https://github.com/socketry/async/blob/main/context/scheduler.md
|
|
39
|
-
- https://github.com/socketry/async/blob/main/lib/async/scheduler.rb#L28
|
|
40
|
-
-
|
|
41
|
-
|
|
42
3
|
## useful concurrency tools
|
|
43
4
|
|
|
44
5
|
- debounce
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'bundler/inline'
|
|
4
|
+
|
|
5
|
+
gemfile do
|
|
6
|
+
source 'https://rubygems.org'
|
|
7
|
+
gem 'benchmark'
|
|
8
|
+
gem 'benchmark-ips'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
require 'benchmark/ips'
|
|
12
|
+
|
|
13
|
+
r, w = IO.pipe
|
|
14
|
+
|
|
15
|
+
class IO
|
|
16
|
+
def __fd__
|
|
17
|
+
@__fd__ ||= fileno
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
@map = ObjectSpace::WeakMap.new
|
|
22
|
+
|
|
23
|
+
def cached_fileno(r)
|
|
24
|
+
@map[r] ||= r.fileno
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
Benchmark.ips do |x|
|
|
28
|
+
x.report('IO#fileno') { r.fileno }
|
|
29
|
+
x.report('cached_fileno') { cached_fileno(r) }
|
|
30
|
+
x.report('__fd__') { r.__fd__ }
|
|
31
|
+
|
|
32
|
+
x.compare!(order: :baseline)
|
|
33
|
+
end
|
|
@@ -0,0 +1,85 @@
|
|
|
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'
|
|
9
|
+
gem 'benchmark-ips'
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
require 'benchmark/ips'
|
|
13
|
+
require 'uringmachine'
|
|
14
|
+
require 'thread'
|
|
15
|
+
|
|
16
|
+
COUNT = 10
|
|
17
|
+
CONCURRENCY = (ENV['CONCURRENCY'] || 4).to_i
|
|
18
|
+
|
|
19
|
+
p(CONCURRENCY: CONCURRENCY)
|
|
20
|
+
|
|
21
|
+
STRING = "foo...bar"
|
|
22
|
+
REGEXP = /foo(.+)bar/
|
|
23
|
+
|
|
24
|
+
def threads_setup
|
|
25
|
+
@threads_mutex = Mutex.new
|
|
26
|
+
@threads_start = Queue.new
|
|
27
|
+
@threads_done = Queue.new
|
|
28
|
+
@threads = CONCURRENCY.times.map {
|
|
29
|
+
Thread.new do
|
|
30
|
+
loop do
|
|
31
|
+
@threads_start.shift
|
|
32
|
+
COUNT.times do
|
|
33
|
+
@threads_mutex.synchronize do
|
|
34
|
+
COUNT.times do
|
|
35
|
+
STRING.match(REGEXP)[1]
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
@threads_done << true
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
}
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def threads_run
|
|
46
|
+
@threads_start << true
|
|
47
|
+
@threads_done.shift
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def um_setup
|
|
51
|
+
@um_machine = UM.new
|
|
52
|
+
@um_mutex = UM::Mutex.new
|
|
53
|
+
@um_start = UM::Queue.new
|
|
54
|
+
@um_done = UM::Queue.new
|
|
55
|
+
@fibers = CONCURRENCY.times.map {
|
|
56
|
+
@um_machine.spin do
|
|
57
|
+
loop do
|
|
58
|
+
@um_machine.shift(@um_start)
|
|
59
|
+
COUNT.times do
|
|
60
|
+
@um_machine.synchronize(@um_mutex) do
|
|
61
|
+
COUNT.times do
|
|
62
|
+
STRING.match(REGEXP)[1]
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
@um_machine.push(@um_done, true)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
}
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def um_run
|
|
73
|
+
@um_machine.push(@um_start, true)
|
|
74
|
+
@um_machine.shift(@um_done)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
threads_setup
|
|
78
|
+
um_setup
|
|
79
|
+
|
|
80
|
+
Benchmark.ips do |x|
|
|
81
|
+
x.report("threads") { @threads_run }
|
|
82
|
+
x.report("UM") { @um_run }
|
|
83
|
+
|
|
84
|
+
x.compare!(order: :baseline)
|
|
85
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
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'
|
|
9
|
+
gem 'benchmark-ips'
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
require 'benchmark/ips'
|
|
13
|
+
require 'uringmachine'
|
|
14
|
+
require 'thread'
|
|
15
|
+
|
|
16
|
+
def threads_setup
|
|
17
|
+
@threads_mutex = Mutex.new
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def um_setup
|
|
21
|
+
@um_machine = UM.new
|
|
22
|
+
@um_mutex = UM::Mutex.new
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
threads_setup
|
|
26
|
+
um_setup
|
|
27
|
+
|
|
28
|
+
Benchmark.ips do |x|
|
|
29
|
+
x.report("threads") { @threads_mutex.synchronize { } }
|
|
30
|
+
x.report("UM") { @um_machine.synchronize(@um_mutex) {} }
|
|
31
|
+
|
|
32
|
+
x.compare!(order: :baseline)
|
|
33
|
+
end
|
data/examples/bm_queue.rb
CHANGED
|
@@ -5,24 +5,26 @@ require 'bundler/inline'
|
|
|
5
5
|
gemfile do
|
|
6
6
|
source 'https://rubygems.org'
|
|
7
7
|
gem 'uringmachine', path: '..'
|
|
8
|
+
gem 'benchmark'
|
|
8
9
|
gem 'benchmark-ips'
|
|
9
10
|
end
|
|
10
11
|
|
|
11
12
|
require 'benchmark/ips'
|
|
12
|
-
|
|
13
|
+
require_relative '../lib/uringmachine'
|
|
13
14
|
|
|
14
15
|
COUNT = 1000
|
|
15
|
-
NUM_PRODUCERS =
|
|
16
|
-
NUM_CONSUMERS =
|
|
16
|
+
NUM_PRODUCERS = 8
|
|
17
|
+
NUM_CONSUMERS = 8
|
|
18
|
+
|
|
19
|
+
@queue = Queue.new
|
|
20
|
+
@done = Queue.new
|
|
17
21
|
|
|
18
22
|
def run_threads
|
|
19
|
-
queue = Queue.new
|
|
20
|
-
done = Queue.new
|
|
21
23
|
|
|
22
24
|
NUM_PRODUCERS.times do
|
|
23
25
|
Thread.new do
|
|
24
|
-
COUNT.times { queue << rand(1000) }
|
|
25
|
-
done << true
|
|
26
|
+
COUNT.times { @queue << rand(1000) }
|
|
27
|
+
@done << true
|
|
26
28
|
end
|
|
27
29
|
end
|
|
28
30
|
|
|
@@ -30,65 +32,64 @@ def run_threads
|
|
|
30
32
|
NUM_CONSUMERS.times do
|
|
31
33
|
Thread.new do
|
|
32
34
|
loop do
|
|
33
|
-
item = queue.shift
|
|
35
|
+
item = @queue.shift
|
|
34
36
|
break if item.nil?
|
|
35
37
|
|
|
36
38
|
total += item
|
|
37
39
|
end
|
|
38
|
-
done << true
|
|
40
|
+
@done << true
|
|
39
41
|
end
|
|
40
42
|
end
|
|
41
43
|
|
|
42
44
|
# wait for producers
|
|
43
|
-
NUM_PRODUCERS.times { done.shift }
|
|
45
|
+
NUM_PRODUCERS.times { @done.shift }
|
|
44
46
|
|
|
45
47
|
# stop and wait for consumers
|
|
46
48
|
NUM_CONSUMERS.times do
|
|
47
|
-
queue << nil
|
|
48
|
-
done.shift
|
|
49
|
+
@queue << nil
|
|
50
|
+
@done.shift
|
|
49
51
|
end
|
|
50
52
|
|
|
51
53
|
total
|
|
52
54
|
end
|
|
53
55
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
done = UM::Queue.new
|
|
56
|
+
@machine = UM.new
|
|
57
|
+
@um_queue = UM::Queue.new
|
|
58
|
+
@um_done = UM::Queue.new
|
|
58
59
|
|
|
60
|
+
def run_um
|
|
59
61
|
NUM_PRODUCERS.times do
|
|
60
|
-
machine.spin do
|
|
61
|
-
COUNT.times { machine.push(
|
|
62
|
-
machine.push(
|
|
62
|
+
@machine.spin do
|
|
63
|
+
COUNT.times { @machine.push(@um_queue, rand(1000)) }
|
|
64
|
+
@machine.push(@um_done, true)
|
|
63
65
|
end
|
|
64
66
|
end
|
|
65
67
|
|
|
66
68
|
total = 0
|
|
67
69
|
NUM_CONSUMERS.times do
|
|
68
|
-
machine.spin do
|
|
70
|
+
@machine.spin do
|
|
69
71
|
loop do
|
|
70
|
-
item = machine.shift(
|
|
72
|
+
item = @machine.shift(@um_queue)
|
|
71
73
|
break if item.nil?
|
|
72
74
|
|
|
73
75
|
total += item
|
|
74
76
|
end
|
|
75
|
-
machine.push(
|
|
77
|
+
@machine.push(@um_done, true)
|
|
76
78
|
end
|
|
77
79
|
end
|
|
78
80
|
|
|
79
81
|
# wait for producers
|
|
80
|
-
NUM_PRODUCERS.times { machine.shift(
|
|
82
|
+
NUM_PRODUCERS.times { @machine.shift(@um_done) }
|
|
81
83
|
|
|
82
84
|
# stop and wait for consumers
|
|
83
85
|
NUM_CONSUMERS.times do
|
|
84
|
-
machine.push(
|
|
85
|
-
machine.shift(
|
|
86
|
+
@machine.push(@um_queue, nil)
|
|
87
|
+
@machine.shift(@um_done)
|
|
86
88
|
end
|
|
87
89
|
|
|
88
90
|
total
|
|
89
91
|
end
|
|
90
92
|
|
|
91
|
-
|
|
92
93
|
# puts "running"
|
|
93
94
|
# res = run_threads
|
|
94
95
|
# p threads: res
|
|
@@ -98,14 +99,13 @@ end
|
|
|
98
99
|
# p fibers: res
|
|
99
100
|
# }
|
|
100
101
|
|
|
101
|
-
|
|
102
102
|
# __END__
|
|
103
103
|
|
|
104
104
|
Benchmark.ips do |x|
|
|
105
|
-
x.config(:time =>
|
|
105
|
+
x.config(:time => 10, :warmup => 3)
|
|
106
106
|
|
|
107
107
|
x.report("threads") { run_threads }
|
|
108
108
|
x.report("UM") { run_um }
|
|
109
109
|
|
|
110
|
-
x.compare!
|
|
110
|
+
x.compare!(order: :baseline)
|
|
111
111
|
end
|
data/examples/bm_send.rb
CHANGED
|
@@ -71,10 +71,6 @@ def um_send_bundle
|
|
|
71
71
|
@machine.send_bundle(@server_fd, @bgid, @parts)
|
|
72
72
|
end
|
|
73
73
|
|
|
74
|
-
# um_send_bundle
|
|
75
|
-
# 10.times { @machine.snooze }
|
|
76
|
-
# exit
|
|
77
|
-
|
|
78
74
|
p(STR_COUNT:, STR_SIZE:)
|
|
79
75
|
|
|
80
76
|
Benchmark.ips do |x|
|
|
@@ -82,5 +78,6 @@ Benchmark.ips do |x|
|
|
|
82
78
|
x.report('UM#write') { um_write }
|
|
83
79
|
x.report('UM#send') { um_send }
|
|
84
80
|
x.report('UM#send_bundle') { um_send_bundle }
|
|
85
|
-
|
|
81
|
+
|
|
82
|
+
x.compare!(order: :baseline)
|
|
86
83
|
end
|
data/examples/bm_snooze.rb
CHANGED
|
@@ -15,37 +15,19 @@ ITERATIONS = 1000
|
|
|
15
15
|
|
|
16
16
|
$machine = UringMachine.new
|
|
17
17
|
|
|
18
|
-
def
|
|
18
|
+
def run_snooze_um
|
|
19
19
|
count = 0
|
|
20
|
-
main = Fiber.current
|
|
21
20
|
|
|
22
|
-
f1 =
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
else
|
|
29
|
-
$machine.snooze
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
end
|
|
21
|
+
f1 = $machine.spin {
|
|
22
|
+
ITERATIONS.times { count += 1; $machine.snooze }
|
|
23
|
+
}
|
|
24
|
+
f2 = $machine.spin {
|
|
25
|
+
ITERATIONS.times { count += 1; $machine.snooze }
|
|
26
|
+
}
|
|
33
27
|
|
|
34
|
-
|
|
35
|
-
loop do
|
|
36
|
-
count += 1
|
|
37
|
-
if count == ITERATIONS
|
|
38
|
-
$machine.schedule(main, nil)
|
|
39
|
-
break
|
|
40
|
-
else
|
|
41
|
-
$machine.snooze
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
end
|
|
28
|
+
$machine.join(f1, f2)
|
|
45
29
|
|
|
46
|
-
|
|
47
|
-
$machine.schedule(f2, nil)
|
|
48
|
-
$machine.yield
|
|
30
|
+
count
|
|
49
31
|
end
|
|
50
32
|
|
|
51
33
|
def run_raw_transfer
|
|
@@ -53,36 +35,32 @@ def run_raw_transfer
|
|
|
53
35
|
main = Fiber.current
|
|
54
36
|
f2 = nil
|
|
55
37
|
f1 = Fiber.new do
|
|
56
|
-
|
|
38
|
+
ITERATIONS.times do
|
|
57
39
|
count += 1
|
|
58
|
-
|
|
59
|
-
main.transfer(nil)
|
|
60
|
-
break
|
|
61
|
-
else
|
|
62
|
-
f2.transfer(nil)
|
|
63
|
-
end
|
|
40
|
+
f2.transfer(nil)
|
|
64
41
|
end
|
|
65
42
|
end
|
|
66
43
|
|
|
67
44
|
f2 = Fiber.new do
|
|
68
|
-
|
|
45
|
+
ITERATIONS.times do
|
|
69
46
|
count += 1
|
|
70
|
-
|
|
71
|
-
main.transfer(nil)
|
|
72
|
-
break
|
|
73
|
-
else
|
|
74
|
-
f1.transfer(nil)
|
|
75
|
-
end
|
|
47
|
+
f1.transfer(nil)
|
|
76
48
|
end
|
|
49
|
+
main.transfer(nil)
|
|
77
50
|
end
|
|
78
51
|
|
|
79
52
|
f1.transfer(nil)
|
|
53
|
+
|
|
54
|
+
count
|
|
80
55
|
end
|
|
81
56
|
|
|
57
|
+
p run_snooze_um: run_snooze_um
|
|
58
|
+
p run_raw_transfer: run_raw_transfer
|
|
59
|
+
|
|
82
60
|
bm = Benchmark.ips do |x|
|
|
83
61
|
x.config(:time => 5, :warmup => 2)
|
|
84
62
|
|
|
85
|
-
x.report("
|
|
63
|
+
x.report("snooze_um") { run_snooze_um }
|
|
86
64
|
x.report("raw transfer") { run_raw_transfer }
|
|
87
65
|
|
|
88
66
|
x.compare!
|
data/examples/bm_write.rb
CHANGED
|
@@ -11,7 +11,7 @@ end
|
|
|
11
11
|
require 'benchmark'
|
|
12
12
|
require 'uringmachine'
|
|
13
13
|
|
|
14
|
-
ITERATIONS =
|
|
14
|
+
ITERATIONS = 10000
|
|
15
15
|
BUF = ('*' * 8192).freeze
|
|
16
16
|
FN = '/tmp/bm_write'
|
|
17
17
|
|
|
@@ -47,6 +47,9 @@ ensure
|
|
|
47
47
|
fio.close
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
+
run_io_write(1)
|
|
51
|
+
run_um_write(1)
|
|
52
|
+
|
|
50
53
|
Benchmark.bm do |x|
|
|
51
54
|
[1, 2, 4, 8].each do |c|
|
|
52
55
|
x.report("IO (#{c} threads)") { run_io_write(c) }
|
|
@@ -1,71 +1,35 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
require 'bundler/setup'
|
|
4
|
+
|
|
5
|
+
require 'uringmachine'
|
|
6
|
+
require 'uringmachine/fiber_scheduler'
|
|
5
7
|
require 'net/http'
|
|
6
8
|
|
|
7
|
-
machine = UringMachine.new
|
|
8
|
-
scheduler = UM::FiberScheduler.new(machine)
|
|
9
|
+
$machine = UringMachine.new
|
|
10
|
+
scheduler = UM::FiberScheduler.new($machine)
|
|
9
11
|
Fiber.set_scheduler scheduler
|
|
10
12
|
|
|
11
13
|
i, o = IO.pipe
|
|
12
14
|
|
|
13
15
|
f1 = Fiber.schedule do
|
|
14
|
-
|
|
15
|
-
# o.write 'Hello, world!'
|
|
16
|
-
# o.close
|
|
16
|
+
puts "Hello from fiber 1!!!"
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
f2 = Fiber.schedule do
|
|
20
|
-
|
|
21
|
-
# 10.times do
|
|
22
|
-
# sleep 0.1
|
|
23
|
-
# puts "."
|
|
24
|
-
# end
|
|
20
|
+
puts "Hello from fiber 2!!!"
|
|
25
21
|
end
|
|
26
22
|
|
|
27
|
-
# Fiber.schedule do
|
|
28
|
-
# scheduler.block(:wait)
|
|
29
|
-
# end
|
|
30
|
-
|
|
31
23
|
f3 = Fiber.schedule do
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
# scheduler.p e
|
|
36
|
-
# scheduler.p e.backtrace
|
|
24
|
+
o.write 'hello'
|
|
25
|
+
puts "wrote it!"
|
|
26
|
+
o.close
|
|
37
27
|
end
|
|
38
28
|
|
|
39
29
|
f4 = Fiber.schedule do
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
# tcp.timeout = 10
|
|
43
|
-
# scheduler.p tcp
|
|
44
|
-
# tcp << "GET / HTTP/1.1\r\nHost: noteflakes.com\r\n\r\n"
|
|
45
|
-
# s = tcp.read
|
|
46
|
-
# scheduler.p s: s
|
|
47
|
-
ret = Net::HTTP.get('noteflakes.com', '/ping')
|
|
48
|
-
scheduler.p ret: ret
|
|
49
|
-
rescue => e
|
|
50
|
-
scheduler.p e
|
|
51
|
-
scheduler.p e.backtrace
|
|
30
|
+
str = i.read
|
|
31
|
+
puts "got: #{str}"
|
|
52
32
|
end
|
|
53
33
|
|
|
54
|
-
scheduler.join
|
|
55
|
-
|
|
56
|
-
__END__
|
|
57
|
-
|
|
58
|
-
stdout_fd = STDOUT.fileno
|
|
59
|
-
stdin_fd = STDIN.fileno
|
|
60
|
-
machine.write(stdout_fd, "Hello, world!\n")
|
|
61
|
-
|
|
62
|
-
loop do
|
|
63
|
-
machine.write(stdout_fd, "Say something: ")
|
|
64
|
-
buf = +''
|
|
65
|
-
res = machine.read(stdin_fd, buf, 8192)
|
|
66
|
-
if res > 0
|
|
67
|
-
machine.write(stdout_fd, "You said: #{buf}")
|
|
68
|
-
else
|
|
69
|
-
break
|
|
70
|
-
end
|
|
71
|
-
end
|
|
34
|
+
# scheduler.join
|
|
35
|
+
# Fiber.set_scheduler(nil)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'bundler/setup'
|
|
4
|
+
|
|
5
|
+
require 'uringmachine'
|
|
6
|
+
require 'uringmachine/fiber_scheduler'
|
|
7
|
+
require 'net/http'
|
|
8
|
+
|
|
9
|
+
$machine = UringMachine.new
|
|
10
|
+
scheduler = UM::FiberScheduler.new($machine)
|
|
11
|
+
Fiber.set_scheduler scheduler
|
|
12
|
+
|
|
13
|
+
p parent: Fiber.scheduler
|
|
14
|
+
p Fiber.current
|
|
15
|
+
|
|
16
|
+
pid = fork do
|
|
17
|
+
Fiber.scheduler.post_fork
|
|
18
|
+
Fiber.set_scheduler nil
|
|
19
|
+
p child: Fiber.scheduler
|
|
20
|
+
# Fiber.scheduler.post_fork
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
Process.wait(pid)
|
|
24
|
+
p :done
|