miner_mover 0.1.1.1 → 0.1.2.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9e2daa3ba8e778e20c25e3a6363683b3163e1141f9438b53be890845acf5440e
4
- data.tar.gz: b72dc662be9c50caa281e087b3708c72a53aa5e593eeb053b59a0679238d568b
3
+ metadata.gz: 4901bb324083ef4c73adb1ed174794d0c90821fe9eae11f7a9935690dab821e3
4
+ data.tar.gz: ad001e368e39ab5e11bc2750d37e6aee4ba6dc42be2e08d0f346f57065c12a88
5
5
  SHA512:
6
- metadata.gz: 3203db4674a641c4a53ebed0cea4aaa445ef9e120ad582bc1cfcc787541ee53a8677eff1e4936429c4eaa72ef686ef97941a7a929d2d5db4e88a678684005962
7
- data.tar.gz: e0052a82fa40bcf19b3382ead683087e52f90e6065751a65ff9475aadd141beb0ebe098673acffe48784f90c672aa5990fe2c0e117a3db4bd1782252af7cec91
6
+ metadata.gz: 22db270f2c03cbbcace66a2724ed8c98315b14caa3d0d135e02e04d98b9baaaa49c9b2bc3aaa7f64b35fd6d5416611e29d344582dbc3cc5820ce351ea0a6b22c
7
+ data.tar.gz: 7ef93f90a90e33c34e3a5412495a828fb9030ccb160389b764448bf5e7e9dfe022687b1db9ba6e64e7418af541a681033d437b21ff50ebba320b18fa4a9c6095
data/README.md CHANGED
@@ -42,51 +42,57 @@ configured via `:work_type`
42
42
 
43
43
  # Usage
44
44
 
45
+ You'll want to use **Ruby 3.1+** (CRuby) to make the most of Ractors, Fibers,
46
+ and Fiber::Scheduler.
47
+
48
+ This gem can be used on JRuby and TruffleRuby, but several concurrency options
49
+ are not available: process forking, Ractors, and Fiber::Scheduler.
50
+ However, their threading performance exceeds CRuby's as they don't have a
51
+ Global VM Lock (GVL).
52
+
45
53
  ## Install
46
54
 
47
- You'll want to use **Ruby 3.x** (CRuby) to make the most of Fibers.
55
+ Right now, a gem installation only provides the Miner Mover library.
56
+ Use the **Development** process below to access all of the demonstration
57
+ scripts showing the different concurrency strategies.
48
58
 
49
- ### Dependencies
59
+ `gem install miner_mover`
50
60
 
51
- * rake
52
- * minitest
53
- * dotcfg
54
- * fiber_scheduler
61
+ For Ruby 3.1+ on linux, you'll also want:
55
62
 
56
- `gem install rake minitest dotcfg fiber_scheduler`
63
+ `gem install fiber_scheduler io-event`
57
64
 
58
- ### Clone
65
+ ## Development
59
66
 
60
67
  ```
61
68
  git clone https://github.com/rickhull/miner_mover
62
69
  cd miner_mover
70
+ bundle config set --local with development
71
+ bundle install
63
72
  ```
64
73
 
65
- ### Try rake
74
+ ### Rake Tasks
66
75
 
67
76
  Try: `rake -T` to see available [Rake tasks](Rakefile)
68
77
 
69
78
  ```
70
79
  $ rake -T
71
80
 
72
- rake alt_demo # run all demos minus fiber_scheduler / ractor / process
73
- rake config # run demo/config
74
- rake default # rake test
75
- rake demo # run all demos
76
- rake fiber # run demo/fiber
77
- rake fiber_scheduler # run demo/fiber_scheduler
78
- rake process_pipe # run demo/process_pipe
79
- rake process_socket # run demo/process_socket
80
- rake ractor # run demo/ractor
81
- rake serial # run demo/serial
81
+ rake config # Run demo/config.rb
82
+ rake demo # Run all demos
83
+ rake fiber # Run demo/fiber.rb
84
+ rake fiber_scheduler # Run demo/fiber_scheduler.rb
85
+ rake jvm_demo # Run JVM compatible demos
86
+ rake process_pipe # Run demo/process_pipe.rb
87
+ rake process_socket # Run demo/process_socket.rb
88
+ rake ractor # Run demo/ractor.rb
89
+ rake serial # Run demo/serial.rb
82
90
  rake test # Run tests
83
- rake thread # run demo/thread
91
+ rake thread # Run demo/thread.rb
84
92
  ```
85
93
 
86
94
  Try: `rake test`
87
95
 
88
- ## Rake Tasks
89
-
90
96
  Included demonstration scripts can be executed via Rake tasks.
91
97
  The following order is recommended:
92
98
 
@@ -101,7 +107,7 @@ The following order is recommended:
101
107
  Try each task; there will be about 6 seconds worth of many lines of output
102
108
  logging. These rake tasks correspond to the scripts within [`demo/`](demo/).
103
109
 
104
- ## Satisfy `LOAD_PATH`
110
+ ### Satisfy `LOAD_PATH`
105
111
 
106
112
  Rake tasks take care of `LOAD_PATH`, so the following is
107
113
  **only necessary when *not* using rake tasks**:
@@ -111,41 +117,81 @@ Rake tasks take care of `LOAD_PATH`, so the following is
111
117
  `require 'miner_mover'` will work.
112
118
  * This project does not use `require_relative`
113
119
 
114
- ## Exploration in `irb`
120
+ ### Exploration in `irb`
115
121
 
116
122
  `$ irb -I lib`
117
123
 
118
124
  ```
119
- irb(main):001:0> include MinerMover
125
+ irb(main):001:0> require 'miner_mover/worker'
126
+ => true
127
+
128
+ irb(main):002:0> include MinerMover
120
129
  => Object
121
130
 
122
- irb(main):002:0> miner = Miner.new
131
+ irb(main):003:0> miner = Miner.new
123
132
  =>
124
- #<MinerMover::Miner:0x00007fdd649754e8
133
+ #<MinerMover::Miner:0x00007fbee8a3a080
125
134
  ...
126
135
 
127
- irb(main):003:0> miner.mine_ore
128
- => 0
129
-
130
- irb(main):004:0> miner.mine_ore 5
131
- => 3
132
-
133
- irb(main):005:0> miner.mine_ore 20
134
- => 6483
135
-
136
- irb(main):006:0> mover = Mover.new
136
+ irb(main):004:0> mover = Mover.new
137
137
  =>
138
- #<MinerMover::Mover:0x00007fdd64979930
138
+ #<MinerMover::Mover:0x00007fbee8a8a6c0
139
139
  ...
140
140
 
141
- irb(main):007:0> mover.load_ore 6483
142
- => 6483
143
-
144
- irb(main):008:0> mover.status
145
- => "Batch 6483 / 10M 0% | Moved 0x (0M)"
141
+ irb(main):005:0> miner.state
142
+ =>
143
+ {:id=>"00050720",
144
+ :logging=>false,
145
+ :debugging=>false,
146
+ :timer=>10200,
147
+ :variance=>0,
148
+ :depth=>5,
149
+ :partial_reward=>false}
150
+
151
+ irb(main):006:0> mover.state
152
+ =>
153
+ {:id=>"00057860",
154
+ :logging=>false,
155
+ :debugging=>false,
156
+ :timer=>10456,
157
+ :variance=>0,
158
+ :work_type=>:cpu,
159
+ :batch_size=>10000000,
160
+ :batch=>0,
161
+ :batches=>0,
162
+ :ore_moved=>0}
163
+
164
+ irb(main):007:0> miner.mine_ore
165
+ => 7
166
+
167
+ irb(main):008:0> mover.load_ore 7
168
+ => 7
169
+
170
+ irb(main):009:0> miner.state
171
+ =>
172
+ {:id=>"00050720",
173
+ :logging=>false,
174
+ :debugging=>false,
175
+ :timer=>28831,
176
+ :variance=>0,
177
+ :depth=>5,
178
+ :partial_reward=>false}
179
+
180
+ irb(main):010:0> mover.state
181
+ =>
182
+ {:id=>"00057860",
183
+ :logging=>false,
184
+ :debugging=>false,
185
+ :timer=>27959,
186
+ :variance=>0,
187
+ :work_type=>:cpu,
188
+ :batch_size=>10000000,
189
+ :batch=>7,
190
+ :batches=>0,
191
+ :ore_moved=>0}
146
192
  ```
147
193
 
148
- ## Included scripts
194
+ ### Included scripts
149
195
 
150
196
  These scripts implement a full miner mover simulation using different
151
197
  multitasking paradigms in Ruby.
@@ -165,6 +211,46 @@ multiple miners or movers.
165
211
 
166
212
  Execute via e.g. `ruby -Ilib demo/thread.rb`
167
213
 
214
+ ### Concurrency Strategies
215
+
216
+ #### [Serial](demo/serial.rb)
217
+
218
+ One miner, one mover. The miner mines to a depth, then loads the ore.
219
+ When the mover has a full batch, the batch is moved while the miner waits.
220
+
221
+ #### [Fibers](demo/fiber.rb)
222
+
223
+ Without a Fiber Scheduler, this just changes some organizational things.
224
+ Again, one miner, one mover. The mover has its own fiber, and the mining
225
+ fiber can pass ore to the moving fiber. There is no concurrency, so the
226
+ performance is roughly the same as before.
227
+
228
+ #### [Fiber Scheduler](demo/fiber_scheduler.rb)
229
+
230
+ TBD
231
+
232
+ #### [Threads](demo/thread.rb)
233
+
234
+ An array of mining threads and an array of moving threads.
235
+ A single shared queue for loading ore from miners to movers.
236
+ All threads contend for the same execution lock (GVL).
237
+
238
+ #### [Ractors](demo/ractor.rb)
239
+
240
+ Moving threads execute in their own ractor.
241
+ Mining threads contend against mining threads. Moving threads, likewise.
242
+
243
+ #### [Processes with pipes](demo/process_pipe.rb)
244
+
245
+ Similar to ractors, but using `Process.fork` for movers, using a pipe to send
246
+ ore from the parent mining process.
247
+
248
+ #### [Processes with sockets](demo/process_socket.rb)
249
+
250
+ As above, but with Unix sockets (*not* network sockets), using any of
251
+ `SOCK_STREAM` `SOCK_DGRAM` `SOCK_SEQPACKET` socket types.
252
+ In all cases, ore amounts are 4 bytes so the types behave roughly equivalently.
253
+
168
254
  # Multitasking
169
255
 
170
256
  *Multitasking* here means "the most general sense of performing several tasks
data/Rakefile CHANGED
@@ -1,27 +1,43 @@
1
- require 'rake/testtask'
1
+ #
2
+ # test task
3
+ #
2
4
 
5
+ require 'rake/testtask'
3
6
  Rake::TestTask.new :test do |t|
4
7
  t.pattern = "test/*.rb"
5
8
  t.warning = true
6
9
  end
7
-
8
- desc "rake test"
9
10
  task default: :test
10
11
 
12
+ #
13
+ # demo tasks
14
+ #
15
+
16
+ if ENV['RUBYOPT'].nil? or ENV['RUBYOPT'].empty?
17
+ flags = ['-I', File.join(__dir__, 'lib')]
18
+ else
19
+ flags = nil # subprocesses will have RUBYOPT
20
+ end
21
+
22
+ # create a rake task to run each script in demo/
11
23
  Dir['demo/*.rb'].each { |demo_path|
12
24
  name = File.basename(demo_path, '.rb')
13
- desc "run demo/#{name}"
14
- task(name) { sh "ruby -Ilib #{demo_path}" }
25
+ desc "Run #{demo_path}"
26
+ task(name) { ruby *flags, demo_path }
15
27
  }
16
28
 
17
29
  # jruby / truffleruby lack fiber_scheduler, Ractor, and Process#fork
18
- desc "run all demos minus fiber_scheduler / ractor / process"
30
+ desc "Run JVM compatible demos"
19
31
  task jvm_demo: [:serial, :fiber, :thread]
20
32
 
21
- desc "run all demos"
33
+ desc "Run all demos"
22
34
  task demo: [:serial, :fiber, :fiber_scheduler,
23
35
  :thread, :ractor, :process_pipe, :process_socket]
24
36
 
37
+ #
38
+ # release tasks
39
+ #
40
+
25
41
  begin
26
42
  require 'buildar'
27
43
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.1.1
1
+ 0.1.2.3
@@ -15,7 +15,7 @@ Signal.trap("INT") {
15
15
  stop_mining = true
16
16
  }
17
17
 
18
- socktype = [:DGRAM, :STREAM, :RAW].sample
18
+ socktype = [:DGRAM, :STREAM, :SEQPACKET].sample
19
19
  run.log "SOCK #{socktype}"
20
20
  csock, psock = UNIXSocket.pair(socktype)
21
21
 
data/lib/miner_mover.rb CHANGED
@@ -3,20 +3,22 @@ module MinerMover
3
3
 
4
4
  # $/ is the default line separator: "\n"
5
5
  def self.puts(str, io = $stdout, separator = LINE_SEP)
6
- self.write_nonblock(io, str + separator)
6
+ self.write(io, str + separator)
7
7
  end
8
8
 
9
- def self.write_nonblock(io, str)
9
+ def self.write(io, str)
10
+ # nonblocking write attempt; ensure the full string is written
10
11
  begin
11
- # nonblocking write attempt; ensure the full string is written
12
- size = str.bytesize
13
12
  num_bytes = io.write_nonblock(str)
14
- # blocking write if nonblocking write comes up short
15
- io.write str.byteslice(num_bytes, size - num_bytes) if num_bytes < size
16
13
  rescue IO::WaitWritable, Errno::EINTR
17
14
  IO.select([], [io]) # wait until writable
18
15
  retry
19
16
  end
17
+ # blocking write if nonblocking write comes up short
18
+ if num_bytes < str.bytesize
19
+ io.write str.byteslice(num_bytes, str.bytesize - num_bytes)
20
+ end
21
+ nil
20
22
  end
21
23
 
22
24
  def self.log_fmt(timer, id, msg)
data/miner_mover.gemspec CHANGED
@@ -5,29 +5,23 @@ Gem::Specification.new do |s|
5
5
  s.description = <<EOF
6
6
  Fundamentally, we have a set of miners and a set of movers. A miner takes some amount of time to mine ore, which is given to a mover. When a mover has enough ore for a full batch, the delivery takes some amount of time before more ore can be loaded.
7
7
  EOF
8
- s.authors = ["Rick Hull"]
8
+ s.authors = ["Rick Hull"]
9
9
  s.homepage = "https://github.com/rickhull/miner_mover"
10
10
  s.license = "LGPL-3.0"
11
11
 
12
- s.required_ruby_version = "~> 2"
12
+ s.required_ruby_version = "> 2"
13
13
 
14
14
  s.version = File.read(File.join(__dir__, 'VERSION')).chomp
15
15
 
16
- s.files = %w[miner_mover.gemspec VERSION README.md Rakefile]
17
- s.files += Dir['lib/**/*.rb']
18
- s.files += Dir['test/**/*.rb']
19
- s.files += Dir['demo/**/*.rb']
16
+ s.files = Dir[
17
+ 'miner_mover.gemspec',
18
+ 'VERSION',
19
+ 'README.md',
20
+ 'Rakefile',
21
+ 'lib/**/*.rb',
22
+ 'test/**/*.rb',
23
+ 'demo/**/*.rb',
24
+ ]
20
25
 
21
- s.add_dependency "dotcfg", "~> 1.0"
22
-
23
- s.requirements << "For all features and best performance:"
24
- s.requirements << "gem install rake minitest fiber_scheduler"
25
- s.requirements << "For dev tools:"
26
- s.requirements << "gem install buildar flog flay"
27
-
28
- s.add_development_dependency "rake", "~> 13.0" # CVE-2020-8130
29
- s.add_development_dependency "minitest", "~> 5.0"
30
- s.add_development_dependency "buildar", "~> 3.0"
31
- s.add_development_dependency "flog", "~> 0"
32
- s.add_development_dependency "flay", "~> 0"
26
+ s.add_runtime_dependency "dotcfg", "~> 1.0"
33
27
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: miner_mover
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1.1
4
+ version: 0.1.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rick Hull
@@ -24,76 +24,6 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.0'
27
- - !ruby/object:Gem::Dependency
28
- name: rake
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '13.0'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '13.0'
41
- - !ruby/object:Gem::Dependency
42
- name: minitest
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '5.0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '5.0'
55
- - !ruby/object:Gem::Dependency
56
- name: buildar
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: '3.0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: '3.0'
69
- - !ruby/object:Gem::Dependency
70
- name: flog
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: flay
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - "~>"
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - "~>"
95
- - !ruby/object:Gem::Version
96
- version: '0'
97
27
  description: 'Fundamentally, we have a set of miners and a set of movers. A miner
98
28
  takes some amount of time to mine ore, which is given to a mover. When a mover has
99
29
  enough ore for a full batch, the delivery takes some amount of time before more
@@ -133,7 +63,7 @@ require_paths:
133
63
  - lib
134
64
  required_ruby_version: !ruby/object:Gem::Requirement
135
65
  requirements:
136
- - - "~>"
66
+ - - ">"
137
67
  - !ruby/object:Gem::Version
138
68
  version: '2'
139
69
  required_rubygems_version: !ruby/object:Gem::Requirement
@@ -141,12 +71,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
141
71
  - - ">="
142
72
  - !ruby/object:Gem::Version
143
73
  version: '0'
144
- requirements:
145
- - 'For all features and best performance:'
146
- - gem install rake minitest fiber_scheduler
147
- - 'For dev tools:'
148
- - gem install buildar flog flay
149
- rubygems_version: 3.3.20
74
+ requirements: []
75
+ rubygems_version: 3.4.1
150
76
  signing_key:
151
77
  specification_version: 4
152
78
  summary: This project provides a basic concurrency problem useful for exploring different