concurrently 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +5 -0
  3. data/.rspec +4 -0
  4. data/.travis.yml +16 -0
  5. data/.yardopts +7 -0
  6. data/Gemfile +17 -0
  7. data/LICENSE +176 -0
  8. data/README.md +129 -0
  9. data/RELEASE_NOTES.md +49 -0
  10. data/Rakefile +28 -0
  11. data/concurrently.gemspec +33 -0
  12. data/ext/Ruby/thread.rb +28 -0
  13. data/ext/all/array.rb +24 -0
  14. data/ext/mruby/array.rb +19 -0
  15. data/ext/mruby/fiber.rb +5 -0
  16. data/ext/mruby/io.rb +54 -0
  17. data/guides/Installation.md +46 -0
  18. data/guides/Overview.md +335 -0
  19. data/guides/Performance.md +140 -0
  20. data/guides/Troubleshooting.md +262 -0
  21. data/lib/Ruby/concurrently.rb +12 -0
  22. data/lib/Ruby/concurrently/error.rb +4 -0
  23. data/lib/Ruby/concurrently/event_loop.rb +24 -0
  24. data/lib/Ruby/concurrently/event_loop/io_selector.rb +38 -0
  25. data/lib/all/concurrently/error.rb +10 -0
  26. data/lib/all/concurrently/evaluation.rb +109 -0
  27. data/lib/all/concurrently/evaluation/error.rb +18 -0
  28. data/lib/all/concurrently/event_loop.rb +101 -0
  29. data/lib/all/concurrently/event_loop/fiber.rb +37 -0
  30. data/lib/all/concurrently/event_loop/io_selector.rb +42 -0
  31. data/lib/all/concurrently/event_loop/proc_fiber_pool.rb +18 -0
  32. data/lib/all/concurrently/event_loop/run_queue.rb +111 -0
  33. data/lib/all/concurrently/proc.rb +233 -0
  34. data/lib/all/concurrently/proc/evaluation.rb +246 -0
  35. data/lib/all/concurrently/proc/fiber.rb +67 -0
  36. data/lib/all/concurrently/version.rb +8 -0
  37. data/lib/all/io.rb +248 -0
  38. data/lib/all/kernel.rb +201 -0
  39. data/lib/mruby/concurrently/proc.rb +21 -0
  40. data/lib/mruby/kernel.rb +15 -0
  41. data/mrbgem.rake +42 -0
  42. data/perf/_shared/stage.rb +33 -0
  43. data/perf/concurrent_proc_call.rb +13 -0
  44. data/perf/concurrent_proc_call_and_forget.rb +15 -0
  45. data/perf/concurrent_proc_call_detached.rb +15 -0
  46. data/perf/concurrent_proc_call_nonblock.rb +13 -0
  47. data/perf/concurrent_proc_calls.rb +49 -0
  48. data/perf/concurrent_proc_calls_awaiting.rb +48 -0
  49. metadata +144 -0
@@ -0,0 +1,21 @@
1
+ module Concurrently
2
+ # @api mruby_patches
3
+ # @since 1.0.0
4
+ #
5
+ # mruby's Proc does not support instance variables. So, whe have to make
6
+ # it a normal class that does not inherit from Proc :(
7
+ class Proc
8
+ def initialize(evaluation_class = Evaluation, &proc)
9
+ @evaluation_class = evaluation_class
10
+ @proc = proc
11
+ end
12
+
13
+ def arity
14
+ @proc.arity
15
+ end
16
+
17
+ def __proc_call__(*args)
18
+ @proc.call *args
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,15 @@
1
+ # @api mruby_patches
2
+ # @since 1.0.0
3
+ module Kernel
4
+ # Reimplements Kernel#concurrently. mruby does not support Proc.new without
5
+ # a block.
6
+ private def concurrently(*args, &block)
7
+ Concurrently::Proc.new(&block).call_and_forget *args
8
+ end
9
+
10
+ # Reimplements Kernel#concurrent_proc. mruby does not support Proc.new without
11
+ # a block.
12
+ private def concurrent_proc(evaluation_class = Concurrently::Proc::Evaluation, &block)
13
+ Concurrently::Proc.new(evaluation_class, &block)
14
+ end
15
+ end
data/mrbgem.rake ADDED
@@ -0,0 +1,42 @@
1
+ require_relative 'lib/all/concurrently/version'
2
+
3
+ MRuby::Gem::Specification.new('mruby-concurrently') do |spec|
4
+ spec.version = Concurrently::VERSION
5
+ spec.summary = %q{A concurrency framework based on fibers}
6
+ spec.description = <<-DESC
7
+ Concurrently is a concurrency framework for Ruby and mruby. With it, concurrent
8
+ code can be written sequentially similar to async/await.
9
+
10
+ The concurrency primitive of Concurrently is the concurrent proc. It is very
11
+ similar to a regular proc. Calling a concurrent proc creates a concurrent
12
+ evaluation which is kind of a lightweight thread: It can wait for stuff without
13
+ blocking other concurrent evaluations.
14
+
15
+ Under the hood, concurrent procs are evaluated inside fibers. They can wait for
16
+ readiness of I/O or a period of time (or the result of other concurrent
17
+ evaluations).
18
+ DESC
19
+
20
+ spec.homepage = "https://github.com/christopheraue/m-ruby-concurrently"
21
+ spec.license = 'Apache-2.0'
22
+ spec.authors = ['Christopher Aue']
23
+
24
+ # patch build process so we can set source files with spec.rbfiles
25
+ @generate_functions = true
26
+ @objs << objfile("#{build_dir}/gem_init")
27
+
28
+ spec.rbfiles =
29
+ Dir["#{spec.dir}/ext/all/**/*.rb"].sort +
30
+ Dir["#{spec.dir}/ext/mruby/**/*.rb"].sort +
31
+ Dir["#{spec.dir}/lib/all/**/*.rb"].sort +
32
+ Dir["#{spec.dir}/lib/mruby/**/*.rb"].sort
33
+ spec.test_rbfiles = Dir["#{spec.dir}/test/mruby/*.rb"]
34
+
35
+ spec.add_dependency 'mruby-array-ext'
36
+ spec.add_dependency 'mruby-numeric-ext'
37
+ spec.add_dependency 'mruby-enumerator'
38
+ spec.add_dependency 'mruby-fiber'
39
+ spec.add_dependency 'mruby-time'
40
+ spec.add_dependency 'mruby-io'
41
+ spec.add_dependency 'mruby-callbacks_attachable', '~> 2.2', github: 'christopheraue/m-ruby-callbacks_attachable'
42
+ end
@@ -0,0 +1,33 @@
1
+ require 'bundler'
2
+
3
+ Bundler.require :default
4
+ Bundler.require :perf
5
+
6
+ class Stage
7
+ def measure(seconds: 1) # &test
8
+ GC.start
9
+ GC.disable
10
+ profile = RubyProf::Profile.new(merge_fibers: true).tap(&:start) if ARGV[0] == 'profile'
11
+
12
+ event_loop = Concurrently::EventLoop.current
13
+ event_loop.reinitialize!
14
+ iterations = 0
15
+ start_time = event_loop.lifetime
16
+ end_time = start_time + seconds
17
+ while event_loop.lifetime < end_time
18
+ yield
19
+ iterations += 1
20
+ end
21
+ stop_time = event_loop.lifetime
22
+
23
+ if ARGV[0] == 'profile'
24
+ printer = ARGV[1].dup || 'flat'
25
+ printer[0] = printer[0].capitalize
26
+ RubyProf.const_get("#{printer}Printer").new(profile.stop).print(STDOUT, sort_method: :self_time)
27
+ end
28
+ GC.enable
29
+
30
+ { iterations: iterations, time: (stop_time-start_time) }
31
+ end
32
+ end
33
+
@@ -0,0 +1,13 @@
1
+ #!/bin/env ruby
2
+
3
+ require_relative "_shared/stage"
4
+
5
+ stage = Stage.new
6
+
7
+ conproc = concurrent_proc{}
8
+
9
+ result = stage.measure(seconds: 1) do
10
+ conproc.call
11
+ end
12
+
13
+ puts "#{result[:iterations]} executions in #{result[:time].round 4} seconds"
@@ -0,0 +1,15 @@
1
+ #!/bin/env ruby
2
+
3
+ require_relative "_shared/stage"
4
+
5
+ stage = Stage.new
6
+
7
+ evaluation = Concurrently::Evaluation.current
8
+ conproc = concurrent_proc{ evaluation.resume! }
9
+
10
+ result = stage.measure(seconds: 1) do
11
+ conproc.call_and_forget
12
+ await_resume!
13
+ end
14
+
15
+ puts "#{result[:iterations]} executions in #{result[:time].round 4} seconds"
@@ -0,0 +1,15 @@
1
+ #!/bin/env ruby
2
+
3
+ require_relative "_shared/stage"
4
+
5
+ stage = Stage.new
6
+
7
+ evaluation = Concurrently::Evaluation.current
8
+ conproc = concurrent_proc{ evaluation.resume! }
9
+
10
+ result = stage.measure(seconds: 1) do
11
+ conproc.call_detached
12
+ await_resume!
13
+ end
14
+
15
+ puts "#{result[:iterations]} executions in #{result[:time].round 4} seconds"
@@ -0,0 +1,13 @@
1
+ #!/bin/env ruby
2
+
3
+ require_relative "_shared/stage"
4
+
5
+ stage = Stage.new
6
+
7
+ conproc = concurrent_proc{}
8
+
9
+ result = stage.measure(seconds: 1) do
10
+ conproc.call_nonblock
11
+ end
12
+
13
+ puts "#{result[:iterations]} executions in #{result[:time].round 4} seconds"
@@ -0,0 +1,49 @@
1
+ #!/bin/env ruby
2
+
3
+ require_relative "_shared/stage"
4
+
5
+ stage = Stage.new
6
+ format = " %-25s %7d executions in %2.4f seconds"
7
+
8
+ puts <<-DOC
9
+ Benchmarked Code
10
+ ----------------
11
+ proc = proc{}
12
+ conproc = concurrent_proc{}
13
+
14
+ while elapsed_seconds < 1
15
+ # CODE #
16
+ end
17
+
18
+ Results
19
+ -------
20
+ # CODE #
21
+ DOC
22
+
23
+ proc = proc{}
24
+ conproc = concurrent_proc{}
25
+
26
+ result = stage.measure(seconds: 1) do
27
+ proc.call
28
+ end
29
+ puts sprintf(format, "proc.call:", result[:iterations], result[:time])
30
+
31
+ result = stage.measure(seconds: 1) do
32
+ conproc.call
33
+ end
34
+ puts sprintf(format, "conproc.call:", result[:iterations], result[:time])
35
+
36
+ result = stage.measure(seconds: 1) do
37
+ conproc.call_nonblock
38
+ end
39
+ puts sprintf(format, "conproc.call_nonblock:", result[:iterations], result[:time])
40
+
41
+ result = stage.measure(seconds: 1) do
42
+ conproc.call_detached
43
+ end
44
+ puts sprintf(format, "conproc.call_detached:", result[:iterations], result[:time])
45
+
46
+ result = stage.measure(seconds: 1) do
47
+ conproc.call_and_forget
48
+ end
49
+ puts sprintf(format, "conproc.call_and_forget:", result[:iterations], result[:time])
@@ -0,0 +1,48 @@
1
+ #!/bin/env ruby
2
+
3
+ require_relative "_shared/stage"
4
+
5
+ stage = Stage.new
6
+ format = " %-25s %7d executions in %2.4f seconds"
7
+ factor = ARGV.fetch(0, 1).to_i
8
+
9
+ puts <<-DOC
10
+ Benchmarked Code
11
+ ----------------
12
+ conproc = concurrent_proc{ wait 0 }
13
+
14
+ while elapsed_seconds < 1
15
+ #{factor}.times{ # CODE # }
16
+ wait 0 # to enter the event loop
17
+ end
18
+
19
+ Results
20
+ -------
21
+ # CODE #
22
+ DOC
23
+
24
+ conproc = concurrent_proc{ wait 0 }
25
+
26
+ result = stage.measure(seconds: 1) do
27
+ factor.times{ conproc.call }
28
+ # no need to enter the event loop manually. It already happens in #call
29
+ end
30
+ puts sprintf(format, "conproc.call:", factor*result[:iterations], result[:time])
31
+
32
+ result = stage.measure(seconds: 1) do
33
+ factor.times{ conproc.call_nonblock }
34
+ wait 0
35
+ end
36
+ puts sprintf(format, "conproc.call_nonblock:", factor*result[:iterations], result[:time])
37
+
38
+ result = stage.measure(seconds: 1) do
39
+ factor.times{ conproc.call_detached }
40
+ wait 0
41
+ end
42
+ puts sprintf(format, "conproc.call_detached:", factor*result[:iterations], result[:time])
43
+
44
+ result = stage.measure(seconds: 1) do
45
+ factor.times{ conproc.call_and_forget }
46
+ wait 0
47
+ end
48
+ puts sprintf(format, "conproc.call_and_forget:", factor*result[:iterations], result[:time])
metadata ADDED
@@ -0,0 +1,144 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: concurrently
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Christopher Aue
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-06-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: nio4r
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: hitimes
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.2'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: callbacks_attachable
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.2'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.2'
55
+ description: |
56
+ Concurrently is a concurrency framework for Ruby and mruby. With it, concurrent
57
+ code can be written sequentially similar to async/await.
58
+
59
+ The concurrency primitive of Concurrently is the concurrent proc. It is very
60
+ similar to a regular proc. Calling a concurrent proc creates a concurrent
61
+ evaluation which is kind of a lightweight thread: It can wait for stuff without
62
+ blocking other concurrent evaluations.
63
+
64
+ Under the hood, concurrent procs are evaluated inside fibers. They can wait for
65
+ readiness of I/O or a period of time (or the result of other concurrent
66
+ evaluations).
67
+ email:
68
+ - rubygems@christopheraue.net
69
+ executables: []
70
+ extensions: []
71
+ extra_rdoc_files: []
72
+ files:
73
+ - ".gitignore"
74
+ - ".rspec"
75
+ - ".travis.yml"
76
+ - ".yardopts"
77
+ - Gemfile
78
+ - LICENSE
79
+ - README.md
80
+ - RELEASE_NOTES.md
81
+ - Rakefile
82
+ - concurrently.gemspec
83
+ - ext/Ruby/thread.rb
84
+ - ext/all/array.rb
85
+ - ext/mruby/array.rb
86
+ - ext/mruby/fiber.rb
87
+ - ext/mruby/io.rb
88
+ - guides/Installation.md
89
+ - guides/Overview.md
90
+ - guides/Performance.md
91
+ - guides/Troubleshooting.md
92
+ - lib/Ruby/concurrently.rb
93
+ - lib/Ruby/concurrently/error.rb
94
+ - lib/Ruby/concurrently/event_loop.rb
95
+ - lib/Ruby/concurrently/event_loop/io_selector.rb
96
+ - lib/all/concurrently/error.rb
97
+ - lib/all/concurrently/evaluation.rb
98
+ - lib/all/concurrently/evaluation/error.rb
99
+ - lib/all/concurrently/event_loop.rb
100
+ - lib/all/concurrently/event_loop/fiber.rb
101
+ - lib/all/concurrently/event_loop/io_selector.rb
102
+ - lib/all/concurrently/event_loop/proc_fiber_pool.rb
103
+ - lib/all/concurrently/event_loop/run_queue.rb
104
+ - lib/all/concurrently/proc.rb
105
+ - lib/all/concurrently/proc/evaluation.rb
106
+ - lib/all/concurrently/proc/fiber.rb
107
+ - lib/all/concurrently/version.rb
108
+ - lib/all/io.rb
109
+ - lib/all/kernel.rb
110
+ - lib/mruby/concurrently/proc.rb
111
+ - lib/mruby/kernel.rb
112
+ - mrbgem.rake
113
+ - perf/_shared/stage.rb
114
+ - perf/concurrent_proc_call.rb
115
+ - perf/concurrent_proc_call_and_forget.rb
116
+ - perf/concurrent_proc_call_detached.rb
117
+ - perf/concurrent_proc_call_nonblock.rb
118
+ - perf/concurrent_proc_calls.rb
119
+ - perf/concurrent_proc_calls_awaiting.rb
120
+ homepage: https://github.com/christopheraue/m-ruby-concurrently
121
+ licenses:
122
+ - Apache-2.0
123
+ metadata: {}
124
+ post_install_message:
125
+ rdoc_options: []
126
+ require_paths:
127
+ - lib/Ruby
128
+ required_ruby_version: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: 2.2.7
133
+ required_rubygems_version: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ requirements: []
139
+ rubyforge_project:
140
+ rubygems_version: 2.6.11
141
+ signing_key:
142
+ specification_version: 4
143
+ summary: A concurrency framework based on fibers
144
+ test_files: []