tunemygc 1.0.55 → 1.0.56
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +4 -1
- data/README.md +2 -2
- data/lib/tunemygc/spies/delayed_job.rb +35 -0
- data/lib/tunemygc/spies.rb +11 -2
- data/lib/tunemygc/version.rb +1 -1
- data/test/delayed_job_test_backend.rb +117 -0
- data/test/{test_activejob_interposer.rb → test_active_job_interposer.rb} +0 -0
- data/test/test_delayed_job_interposer.rb +96 -0
- data/tunemygc.gemspec +1 -0
- metadata +29 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c7729fb0e74aeaa4d3015d0e2204c4aaf07c140c
|
4
|
+
data.tar.gz: 73ba3d4ea9b191a881f69eb32477d7fb055b512d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ec0ad98014be93b9416c1d786c09194b24300947a02fe305c5e5d06bc098c9ca5a4928e03523c2697675f7b0286e69e187adc2819a4fdbdb9c0b343b75509018
|
7
|
+
data.tar.gz: 9128687fbac2a36cb712c1fe0005f4b228f10b97785408d98b2f57f84078a6102268a100eb3148b3448bb6c72cbff1a072646a138cc16930bf6eb2a194fd8a8f
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
tunemygc (1.0.
|
4
|
+
tunemygc (1.0.56)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
@@ -46,6 +46,8 @@ GEM
|
|
46
46
|
builder (3.2.2)
|
47
47
|
crack (0.4.2)
|
48
48
|
safe_yaml (~> 1.0.0)
|
49
|
+
delayed_job (4.0.6)
|
50
|
+
activesupport (>= 3.0, < 5.0)
|
49
51
|
erubis (2.7.0)
|
50
52
|
globalid (0.3.0)
|
51
53
|
activesupport (>= 4.1.0)
|
@@ -117,6 +119,7 @@ PLATFORMS
|
|
117
119
|
DEPENDENCIES
|
118
120
|
activejob (~> 4.2, >= 4.2.0)
|
119
121
|
activesupport (~> 4.1)
|
122
|
+
delayed_job (~> 4.0.6, >= 4.0.6)
|
120
123
|
rails
|
121
124
|
rake (~> 10.3)
|
122
125
|
rake-compiler (~> 0.9, >= 0.9.5)
|
data/README.md
CHANGED
@@ -108,9 +108,9 @@ And after some profiling requests, when the process terminates, you can visit th
|
|
108
108
|
|
109
109
|
#### Advanced
|
110
110
|
|
111
|
-
* `RUBY_GC_SPY=action_controller` (Spy on the GC for this type of processing. `action_controller`, `active_job`, `que_job`, `minitest` or `rspec` are supported)
|
111
|
+
* `RUBY_GC_SPY=action_controller` (Spy on the GC for this type of processing. `action_controller`, `active_job`, `delayed_job`, `que_job`, `minitest` or `rspec` are supported)
|
112
112
|
|
113
|
-
Defines what type of processing you would like to sample for GC activity. An Action Controller spy is the default, but [ActiveJob](https://github.com/rails/rails/tree/master/activejob), [que](https://github.com/chanks/que), [minitest](https://github.com/seattlerb/minitest) and [rspec](http://rspec.info) are also supported as experimental features.
|
113
|
+
Defines what type of processing you would like to sample for GC activity. An Action Controller spy is the default, but [ActiveJob](https://github.com/rails/rails/tree/master/activejob), [delayed_job](https://github.com/collectiveidea/delayed_job), [que](https://github.com/chanks/que), [minitest](https://github.com/seattlerb/minitest) and [rspec](http://rspec.info) are also supported as experimental features.
|
114
114
|
|
115
115
|
## How do I use this?
|
116
116
|
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'delayed_job'
|
4
|
+
|
5
|
+
module Delayed
|
6
|
+
module Plugins
|
7
|
+
class TuneMyGcPlugin < Delayed::Plugin
|
8
|
+
callbacks do |lifecycle|
|
9
|
+
lifecycle.around(:invoke_job) do |job, *args, &block|
|
10
|
+
TuneMyGc.processing_started
|
11
|
+
block.call(job, *args)
|
12
|
+
TuneMyGc.processing_ended
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module TuneMyGc
|
20
|
+
module Spies
|
21
|
+
class DelayedJob < TuneMyGc::Spies::Base
|
22
|
+
def install
|
23
|
+
Delayed::Worker.plugins << Delayed::Plugins::TuneMyGcPlugin
|
24
|
+
TuneMyGc.log "hooked: delayed_job"
|
25
|
+
end
|
26
|
+
|
27
|
+
def uninstall
|
28
|
+
TuneMyGc.uninstall_gc_tracepoint
|
29
|
+
TuneMyGc.log "uninstalled GC tracepoint"
|
30
|
+
Delayed::Worker.plugins.delete(Delayed::Plugins::TuneMyGcPlugin)
|
31
|
+
TuneMyGc.log "uninstalled delayed_job spy"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/tunemygc/spies.rb
CHANGED
@@ -8,12 +8,21 @@ module TuneMyGc
|
|
8
8
|
end
|
9
9
|
|
10
10
|
spy :Base, 'base'
|
11
|
+
|
12
|
+
# Web
|
11
13
|
spy :ActionController, 'action_controller'
|
12
|
-
|
13
|
-
|
14
|
+
|
15
|
+
# Manual
|
14
16
|
spy :Manual, 'manual'
|
17
|
+
|
18
|
+
# Tests
|
19
|
+
spy :Minitest, 'minitest'
|
15
20
|
spy :Rspec, 'rspec'
|
21
|
+
|
22
|
+
# Async jobs
|
23
|
+
spy :ActiveJob, 'active_job'
|
16
24
|
spy :QueJob, 'que_job'
|
25
|
+
spy :DelayedJob, 'delayed_job'
|
17
26
|
|
18
27
|
def self.ids
|
19
28
|
current.map do |spy|
|
data/lib/tunemygc/version.rb
CHANGED
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
# An in-memory backend suitable only for testing. Tries to behave as if it were an ORM.
|
4
|
+
module Delayed
|
5
|
+
module Backend
|
6
|
+
module Test
|
7
|
+
class Job
|
8
|
+
attr_accessor :id
|
9
|
+
attr_accessor :priority
|
10
|
+
attr_accessor :attempts
|
11
|
+
attr_accessor :handler
|
12
|
+
attr_accessor :last_error
|
13
|
+
attr_accessor :run_at
|
14
|
+
attr_accessor :locked_at
|
15
|
+
attr_accessor :locked_by
|
16
|
+
attr_accessor :failed_at
|
17
|
+
attr_accessor :queue
|
18
|
+
|
19
|
+
include Delayed::Backend::Base
|
20
|
+
|
21
|
+
cattr_accessor :id
|
22
|
+
self.id = 0
|
23
|
+
|
24
|
+
def initialize(hash = {})
|
25
|
+
self.attempts = 0
|
26
|
+
self.priority = 0
|
27
|
+
self.id = (self.class.id += 1)
|
28
|
+
hash.each { |k, v| send(:"#{k}=", v) }
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.all
|
32
|
+
@jobs ||= []
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.count
|
36
|
+
all.size
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.delete_all
|
40
|
+
all.clear
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.create(attrs = {})
|
44
|
+
new(attrs).tap do |o|
|
45
|
+
o.save
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.create!(*args)
|
50
|
+
create(*args)
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.clear_locks!(worker_name)
|
54
|
+
all.select { |j| j.locked_by == worker_name }.each do |j|
|
55
|
+
j.locked_by = nil
|
56
|
+
j.locked_at = nil
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Find a few candidate jobs to run (in case some immediately get locked by others).
|
61
|
+
def self.find_available(worker_name, limit = 5, max_run_time = Worker.max_run_time) # rubocop:disable CyclomaticComplexity, PerceivedComplexity
|
62
|
+
jobs = all.select do |j|
|
63
|
+
j.run_at <= db_time_now &&
|
64
|
+
(j.locked_at.nil? || j.locked_at < db_time_now - max_run_time || j.locked_by == worker_name) &&
|
65
|
+
!j.failed?
|
66
|
+
end
|
67
|
+
jobs.select! { |j| j.priority <= Worker.max_priority } if Worker.max_priority
|
68
|
+
jobs.select! { |j| j.priority >= Worker.min_priority } if Worker.min_priority
|
69
|
+
jobs.select! { |j| Worker.queues.include?(j.queue) } if Worker.queues.any?
|
70
|
+
jobs.sort_by! { |j| [j.priority, j.run_at] }[0..limit - 1]
|
71
|
+
end
|
72
|
+
|
73
|
+
# Lock this job for this worker.
|
74
|
+
# Returns true if we have the lock, false otherwise.
|
75
|
+
def lock_exclusively!(_max_run_time, worker)
|
76
|
+
now = self.class.db_time_now
|
77
|
+
if locked_by != worker
|
78
|
+
# We don't own this job so we will update the locked_by name and the locked_at
|
79
|
+
self.locked_at = now
|
80
|
+
self.locked_by = worker
|
81
|
+
end
|
82
|
+
|
83
|
+
true
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.db_time_now
|
87
|
+
Time.current
|
88
|
+
end
|
89
|
+
|
90
|
+
def update_attributes(attrs = {})
|
91
|
+
attrs.each { |k, v| send(:"#{k}=", v) }
|
92
|
+
save
|
93
|
+
end
|
94
|
+
|
95
|
+
def destroy
|
96
|
+
self.class.all.delete(self)
|
97
|
+
end
|
98
|
+
|
99
|
+
def save
|
100
|
+
self.run_at ||= Time.current
|
101
|
+
|
102
|
+
self.class.all << self unless self.class.all.include?(self)
|
103
|
+
true
|
104
|
+
end
|
105
|
+
|
106
|
+
def save!
|
107
|
+
save
|
108
|
+
end
|
109
|
+
|
110
|
+
def reload
|
111
|
+
reset
|
112
|
+
self
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
File without changes
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), 'helper')
|
4
|
+
require 'delayed_job'
|
5
|
+
|
6
|
+
Delayed::Worker.delay_jobs = false
|
7
|
+
|
8
|
+
NewsletterJob = Struct.new(:text, :emails) do
|
9
|
+
def perform
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class TestDelayedJobInterposer < TuneMyGcTestCase
|
14
|
+
def setup
|
15
|
+
TuneMyGc.interposer.uninstall
|
16
|
+
end
|
17
|
+
|
18
|
+
def teardown
|
19
|
+
TuneMyGc.interposer = TuneMyGc::Interposer.new([:ActionController])
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_init
|
23
|
+
TuneMyGc.interposer = TuneMyGc::Interposer.new([:DelayedJob])
|
24
|
+
interposer = TuneMyGc.interposer
|
25
|
+
assert !interposer.installed
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_install_uninstall
|
29
|
+
TuneMyGc.interposer = TuneMyGc::Interposer.new([:DelayedJob])
|
30
|
+
interposer = TuneMyGc.interposer
|
31
|
+
interposer.install
|
32
|
+
interposer.on_initialized
|
33
|
+
assert interposer.installed
|
34
|
+
assert_nil interposer.install
|
35
|
+
|
36
|
+
interposer.uninstall
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_gc_hooks
|
40
|
+
TuneMyGc.interposer = TuneMyGc::Interposer.new([:DelayedJob])
|
41
|
+
interposer = TuneMyGc.interposer
|
42
|
+
interposer.install
|
43
|
+
TuneMyGc.interposer.on_initialized
|
44
|
+
|
45
|
+
GC.start(full_mark: true, immediate_sweep: false)
|
46
|
+
GC.start(full_mark: true, immediate_sweep: true)
|
47
|
+
|
48
|
+
stages = []
|
49
|
+
|
50
|
+
while !TuneMyGc.snapshotter.empty?
|
51
|
+
stages << TuneMyGc.snapshotter.deq
|
52
|
+
end
|
53
|
+
|
54
|
+
# Account for incremental GC on 2.2
|
55
|
+
cycles = [:GC_CYCLE_STARTED, :GC_CYCLE_ENTERED]
|
56
|
+
|
57
|
+
assert stages.any?{|s| cycles.include?(s[3]) }
|
58
|
+
|
59
|
+
interposer.uninstall
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_tests_limit
|
63
|
+
TuneMyGc.interposer = TuneMyGc::Interposer.new([:DelayedJob])
|
64
|
+
interposer = TuneMyGc.interposer
|
65
|
+
interposer.install
|
66
|
+
TuneMyGc.interposer.on_initialized
|
67
|
+
|
68
|
+
ENV["RUBY_GC_TUNE"] = "2"
|
69
|
+
|
70
|
+
require 'delayed_job_test_backend'
|
71
|
+
Delayed.const_set(:Job, Delayed::Backend::Test::Job)
|
72
|
+
worker = Delayed::Worker.new(:max_priority => nil, :min_priority => nil, :quiet => true)
|
73
|
+
worker.work_off
|
74
|
+
|
75
|
+
run_newsletter_job
|
76
|
+
run_newsletter_job
|
77
|
+
|
78
|
+
stages = []
|
79
|
+
|
80
|
+
while !TuneMyGc.snapshotter.empty?
|
81
|
+
stages << TuneMyGc.snapshotter.deq
|
82
|
+
end
|
83
|
+
|
84
|
+
cycles = [:PROCESSING_STARTED]
|
85
|
+
|
86
|
+
assert stages.any?{|s| cycles.include?(s[3]) }
|
87
|
+
|
88
|
+
interposer.uninstall
|
89
|
+
ensure
|
90
|
+
ENV["RUBY_GC_TUNE"] = "1"
|
91
|
+
end
|
92
|
+
|
93
|
+
def run_newsletter_job
|
94
|
+
Delayed::Job.enqueue NewsletterJob.new("test", %w(lourens@bearmetal.eu))
|
95
|
+
end
|
96
|
+
end
|
data/tunemygc.gemspec
CHANGED
@@ -27,4 +27,5 @@ Gem::Specification.new do |s|
|
|
27
27
|
s.add_development_dependency('rake-compiler', '~> 0.9', '>= 0.9.5')
|
28
28
|
s.add_development_dependency('webmock', '~> 1.2', '>= 1.2.0')
|
29
29
|
s.add_development_dependency('activejob', '~> 4.2', '>= 4.2.0')
|
30
|
+
s.add_development_dependency('delayed_job', '~> 4.0.6', '>= 4.0.6')
|
30
31
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tunemygc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.56
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bear Metal
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-04-
|
11
|
+
date: 2015-04-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -98,6 +98,26 @@ dependencies:
|
|
98
98
|
- - ">="
|
99
99
|
- !ruby/object:Gem::Version
|
100
100
|
version: 4.2.0
|
101
|
+
- !ruby/object:Gem::Dependency
|
102
|
+
name: delayed_job
|
103
|
+
requirement: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - "~>"
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: 4.0.6
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 4.0.6
|
111
|
+
type: :development
|
112
|
+
prerelease: false
|
113
|
+
version_requirements: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 4.0.6
|
118
|
+
- - ">="
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: 4.0.6
|
101
121
|
description: Agent for the GC tuning webservice https://www.tunemygc.com - optimal
|
102
122
|
settings for throughput and memory usage of Ruby applications
|
103
123
|
email:
|
@@ -133,6 +153,7 @@ files:
|
|
133
153
|
- lib/tunemygc/spies/action_controller.rb
|
134
154
|
- lib/tunemygc/spies/active_job.rb
|
135
155
|
- lib/tunemygc/spies/base.rb
|
156
|
+
- lib/tunemygc/spies/delayed_job.rb
|
136
157
|
- lib/tunemygc/spies/manual.rb
|
137
158
|
- lib/tunemygc/spies/minitest.rb
|
138
159
|
- lib/tunemygc/spies/que_job.rb
|
@@ -140,11 +161,13 @@ files:
|
|
140
161
|
- lib/tunemygc/subscriber.rb
|
141
162
|
- lib/tunemygc/syncer.rb
|
142
163
|
- lib/tunemygc/version.rb
|
164
|
+
- test/delayed_job_test_backend.rb
|
143
165
|
- test/fixtures.rb
|
144
166
|
- test/helper.rb
|
145
167
|
- test/test_action_controller_interposer.rb
|
146
|
-
- test/
|
168
|
+
- test/test_active_job_interposer.rb
|
147
169
|
- test/test_agent.rb
|
170
|
+
- test/test_delayed_job_interposer.rb
|
148
171
|
- test/test_minitest_interposer.rb
|
149
172
|
- test/test_railtie.rb
|
150
173
|
- test/test_snapshotter.rb
|
@@ -175,11 +198,13 @@ signing_key:
|
|
175
198
|
specification_version: 4
|
176
199
|
summary: TuneMyGC - optimal MRI Ruby 2.1+ Garbage Collection
|
177
200
|
test_files:
|
201
|
+
- test/delayed_job_test_backend.rb
|
178
202
|
- test/fixtures.rb
|
179
203
|
- test/helper.rb
|
180
204
|
- test/test_action_controller_interposer.rb
|
181
|
-
- test/
|
205
|
+
- test/test_active_job_interposer.rb
|
182
206
|
- test/test_agent.rb
|
207
|
+
- test/test_delayed_job_interposer.rb
|
183
208
|
- test/test_minitest_interposer.rb
|
184
209
|
- test/test_railtie.rb
|
185
210
|
- test/test_snapshotter.rb
|