celluloid-task-pooledfiber 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ce7677f3d306f7ab9e1fd473f2a45386a21ec953
4
+ data.tar.gz: 69a81b51fb510f73ffc68137c5f6fea66afdaa3e
5
+ SHA512:
6
+ metadata.gz: 040302514e06883c48056eb92d5e074453ba992e2deb25fb961da5de9d37adf97b084fce49953497afe70e544b10a523d52b198b2cc9945e8021592bf8335dc3
7
+ data.tar.gz: c81f30f0a4aee9ba1b3bf9ea6384f02358f89bd3342c87c1f57f7e19d80a455c8d1899cd0e1bbbd566cea8f54ddfb9356650b0331e2ebe3b111d653713863a88
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.1
4
+ - jruby-19mode
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in celluloid-task-pooled-fiber.gemspec
4
+ gemspec
5
+
6
+ group :test do
7
+ gem 'rake'
8
+ gem 'rspec', '~> 3.2'
9
+ gem 'rspec-retry'
10
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Chris Heald
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,36 @@
1
+ # Celluloid::TaskPooledFiber
2
+
3
+ [![Build Status](https://travis-ci.org/celluloid/celluloid-task-pooledfiber.svg)](https://travis-ci.org/celluloid/celluloid-task-pooledfiber)
4
+
5
+ Provides a Task implementation which reuses a pool of fibers to run tasks. This improves Celluloid's performance.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'celluloid-task-pooledfiber'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install celluloid-task-pooledfiber
20
+
21
+ ## Usage
22
+
23
+ In your application, before starting Celluloid:
24
+
25
+ require 'celluloid/task_pooled_fiber'
26
+ Celluloid.task_class = Celluloid::TaskPooledFiber
27
+
28
+ That's it.
29
+
30
+ ## Contributing
31
+
32
+ 1. Fork it ( https://github.com/celluloid/celluloid-task-pooledfiber/fork )
33
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
34
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
35
+ 4. Push to the branch (`git push origin my-new-feature`)
36
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec) do |spec|
5
+ spec.pattern = 'spec/**/*_spec.rb'
6
+ spec.rspec_opts = ['--color --format documentation']
7
+ end
8
+ task :default => :spec
@@ -0,0 +1,20 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "celluloid-task-pooledfiber"
7
+ spec.version = "0.1.0"
8
+ spec.authors = ["Chris Heald"]
9
+ spec.email = ["cheald@gmail.com"]
10
+
11
+ spec.summary = %q{An alternate Task implementation for Celluloid which improves performance by reusing a pool of fibers to run tasks}
12
+ spec.description = %q{An alternate Task implementation for Celluloid which improves performance by reusing a pool of fibers to run tasks}
13
+ spec.homepage = "http://github.com/celluloid/celluloid-task-pooledfiber"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.require_paths = ["lib"]
18
+
19
+ spec.add_dependency "celluloid", "~> 0.16"
20
+ end
@@ -0,0 +1 @@
1
+ require_relative "../task_pooled_fiber.rb"
@@ -0,0 +1,21 @@
1
+ require 'celluloid'
2
+ require 'thread'
3
+
4
+ module Celluloid
5
+ require_relative './util/fiber_pool'
6
+
7
+ class TaskPooledFiber < TaskFiber
8
+ def self.fiber_pool
9
+ @fiber_pool ||= Util::FiberPool.new
10
+ end
11
+
12
+ def create(&block)
13
+ queue = Thread.current[:celluloid_queue]
14
+ @fiber = TaskPooledFiber.fiber_pool.acquire do
15
+ Thread.current[:celluloid_role] = :actor
16
+ Thread.current[:celluloid_queue] = queue
17
+ block.call
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,95 @@
1
+ module Celluloid
2
+ module Util
3
+ class FiberPool
4
+ attr_accessor :stats
5
+
6
+ def initialize(trim_size = 64)
7
+ @trim_size = trim_size
8
+ @pool = {}
9
+ @stats = { created: 0, acquired: 0, trimmed: 0, sweep_counter: 0, terminated: 0, terminated_threads: 0, sweeps: 0 }
10
+ @mutex = Mutex.new
11
+ end
12
+
13
+ def acquire(&block)
14
+ trim
15
+ sweep
16
+ @stats[:acquired] += 1
17
+ fiber = fiber_pool.shift || create_fiber
18
+ fiber.resume(block)
19
+ fiber
20
+ end
21
+
22
+ private
23
+
24
+ def create_fiber
25
+ pool = fiber_pool
26
+ @stats[:created] += 1
27
+ Fiber.new do |blk|
28
+ loop do
29
+ # At this point, we have a pooled fiber ready for Celluloid to call #resume on.
30
+ Fiber.yield
31
+
32
+ # Once Celluloid resumes the fiber, we need to execute the block the task was
33
+ # created with. This may call suspend/resume; that's fine.
34
+ blk.call
35
+
36
+ # Once Celluloid completes the task, we release this Fiber back to the pool
37
+ pool << Fiber.current
38
+
39
+ # ...and yield for the next #acquire call.
40
+ blk = Fiber.yield
41
+ break if blk == :terminate
42
+ end
43
+ end
44
+ end
45
+
46
+ # If the fiber pool has grown too much, shift off and discard
47
+ # extra fibers so they may be GC'd. This isn't ideal, but it
48
+ # should guard against runaway resource consumption.
49
+ def trim
50
+ pool = fiber_pool
51
+ while pool.length > @trim_size
52
+ @stats[:trimmed] += 1
53
+ pool.shift.resume(:terminate)
54
+ end
55
+ end
56
+
57
+ def sweep
58
+ @mutex.synchronize do
59
+ @stats[:sweep_counter] += 1
60
+ if @stats[:sweep_counter] > 10_000
61
+ alive = []
62
+ Thread.list.each do |thread|
63
+ alive << thread.object_id if thread.alive? && @pool.key?(thread.object_id)
64
+ end
65
+
66
+ (@pool.keys - alive).each do |thread_id|
67
+ @pool[thread_id].each do |_fiber|
68
+ @stats[:terminated] += 1
69
+ # We can't resume the fiber here because we might resume cross-thread
70
+ # TODO: How do we deal with alive fibers in a dead thread?
71
+ # fiber.resume(:terminate)
72
+ end
73
+ @stats[:terminated_threads] += 1
74
+ @pool.delete thread_id
75
+ end
76
+ @stats[:sweep_counter] = 0
77
+ @stats[:sweeps] += 1
78
+ end
79
+ end
80
+ end
81
+
82
+ # Fiber pool for this thread. Fibers can't cross threads, so we have to maintain a
83
+ # pool per thread.
84
+ #
85
+ # We keep our pool in an instance variable rather than in thread locals so that we
86
+ # can sweep out old Fibers from dead threads. This keeps live Fiber instances in
87
+ # a thread local from keeping the thread from being GC'd.
88
+ def fiber_pool
89
+ @mutex.synchronize do
90
+ @pool[Thread.current.object_id] ||= []
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: celluloid-task-pooledfiber
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Chris Heald
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-04-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: celluloid
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '0.16'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '0.16'
27
+ description: An alternate Task implementation for Celluloid which improves performance
28
+ by reusing a pool of fibers to run tasks
29
+ email:
30
+ - cheald@gmail.com
31
+ executables: []
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - .gitignore
36
+ - .rspec
37
+ - .travis.yml
38
+ - Gemfile
39
+ - LICENSE.txt
40
+ - README.md
41
+ - Rakefile
42
+ - celluloid-task-pooledfiber.gemspec
43
+ - lib/celluloid/task/pooled_fiber.rb
44
+ - lib/celluloid/task_pooled_fiber.rb
45
+ - lib/celluloid/util/fiber_pool.rb
46
+ homepage: http://github.com/celluloid/celluloid-task-pooledfiber
47
+ licenses:
48
+ - MIT
49
+ metadata: {}
50
+ post_install_message:
51
+ rdoc_options: []
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - '>='
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - '>='
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ requirements: []
65
+ rubyforge_project:
66
+ rubygems_version: 2.4.6
67
+ signing_key:
68
+ specification_version: 4
69
+ summary: An alternate Task implementation for Celluloid which improves performance
70
+ by reusing a pool of fibers to run tasks
71
+ test_files: []