miner_mover 0.1.1.1 → 0.1.2.3

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: 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