tunemygc 1.0.1
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 +7 -0
- data/.gitignore +4 -0
- data/.travis.yml +19 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +125 -0
- data/README.md +193 -0
- data/Rakefile +32 -0
- data/assets/discourse_bench.png +0 -0
- data/assets/tunemygc-graphic2x-80dac1571cacc70d9b272bb62ae9f6df.png +0 -0
- data/bin/tunemygc +6 -0
- data/ext/tunemygc/extconf.rb +92 -0
- data/ext/tunemygc/getRSS.c +122 -0
- data/ext/tunemygc/tunemygc_ext.c +156 -0
- data/ext/tunemygc/tunemygc_ext.h +21 -0
- data/lib/tunemygc/agent.rb +44 -0
- data/lib/tunemygc/cli.rb +86 -0
- data/lib/tunemygc/configurator.rb +25 -0
- data/lib/tunemygc/interposer.rb +60 -0
- data/lib/tunemygc/railtie.rb +13 -0
- data/lib/tunemygc/request_subscriber.rb +18 -0
- data/lib/tunemygc/snapshotter.rb +49 -0
- data/lib/tunemygc/spies/action_controller.rb +44 -0
- data/lib/tunemygc/subscriber.rb +14 -0
- data/lib/tunemygc/syncer.rb +91 -0
- data/lib/tunemygc/version.rb +5 -0
- data/lib/tunemygc.rb +22 -0
- data/test/fixtures.rb +9 -0
- data/test/helper.rb +30 -0
- data/test/test_agent.rb +21 -0
- data/test/test_interposer.rb +69 -0
- data/test/test_railtie.rb +21 -0
- data/test/test_snapshotter.rb +41 -0
- data/test/test_syncer.rb +146 -0
- data/tunemygc-1.0.gem +0 -0
- data/tunemygc.gemspec +50 -0
- metadata +194 -0
data/test/helper.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
ENV['RUBY_GC_TOKEN'] = 'testapp'
|
4
|
+
|
5
|
+
require 'rails'
|
6
|
+
require 'tunemygc'
|
7
|
+
require "tunemygc/syncer"
|
8
|
+
require 'minitest/autorun'
|
9
|
+
require 'webmock/minitest'
|
10
|
+
|
11
|
+
WebMock.disable_net_connect!
|
12
|
+
|
13
|
+
require File.join(File.dirname(__FILE__), 'fixtures')
|
14
|
+
|
15
|
+
class TuneMyGcTestCase < Minitest::Test
|
16
|
+
if ENV['STRESS_GC'] == '1'
|
17
|
+
def setup
|
18
|
+
GC.stress = true
|
19
|
+
end
|
20
|
+
|
21
|
+
def teardown
|
22
|
+
GC.stress = false
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def process_request(path = '/test')
|
27
|
+
ActiveSupport::Notifications.instrument('start_processing.action_controller', path: path) {}
|
28
|
+
ActiveSupport::Notifications.instrument('process_action.action_controller', path: path) {}
|
29
|
+
end
|
30
|
+
end
|
data/test/test_agent.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), 'helper')
|
4
|
+
|
5
|
+
class TestAgent < TuneMyGcTestCase
|
6
|
+
def test_interposer
|
7
|
+
assert_instance_of TuneMyGc::Interposer, TuneMyGc.interposer
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_snapshotter
|
11
|
+
assert_instance_of TuneMyGc::Snapshotter, TuneMyGc.snapshotter
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_log
|
15
|
+
out, err = capture_io do
|
16
|
+
TuneMyGc.logger = Logger.new($stdout)
|
17
|
+
TuneMyGc.log 'test'
|
18
|
+
end
|
19
|
+
assert_match(/test/, out)
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), 'helper')
|
4
|
+
|
5
|
+
class TestInterposer < TuneMyGcTestCase
|
6
|
+
def setup
|
7
|
+
TuneMyGc.interposer.uninstall
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_init
|
11
|
+
interposer = TuneMyGc.interposer
|
12
|
+
assert !interposer.installed
|
13
|
+
assert_equal [], interposer.spy.subscriptions
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_install_uninstall
|
17
|
+
interposer = TuneMyGc.interposer
|
18
|
+
interposer.install
|
19
|
+
TuneMyGc.interposer.on_initialized
|
20
|
+
|
21
|
+
assert_equal 2, interposer.spy.subscriptions.size
|
22
|
+
assert interposer.installed
|
23
|
+
assert_nil interposer.install
|
24
|
+
|
25
|
+
interposer.uninstall
|
26
|
+
assert_equal [], interposer.spy.subscriptions
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_gc_hooks
|
30
|
+
interposer = TuneMyGc.interposer
|
31
|
+
interposer.install
|
32
|
+
TuneMyGc.interposer.on_initialized
|
33
|
+
|
34
|
+
GC.start(full_mark: true, immediate_sweep: false)
|
35
|
+
GC.start(full_mark: true, immediate_sweep: true)
|
36
|
+
|
37
|
+
stages = []
|
38
|
+
|
39
|
+
while !TuneMyGc.snapshotter.empty?
|
40
|
+
stages << TuneMyGc.snapshotter.deq
|
41
|
+
end
|
42
|
+
|
43
|
+
# Account for incremental GC on 2.2
|
44
|
+
cycles = [:GC_CYCLE_STARTED, :GC_CYCLE_ENTERED]
|
45
|
+
|
46
|
+
assert stages.any?{|s| cycles.include?(s[3]) }
|
47
|
+
|
48
|
+
interposer.uninstall
|
49
|
+
assert_equal [], interposer.spy.subscriptions
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_requests_limit
|
53
|
+
interposer = TuneMyGc.interposer
|
54
|
+
interposer.install
|
55
|
+
TuneMyGc.interposer.on_initialized
|
56
|
+
|
57
|
+
assert_equal 2, interposer.spy.subscriptions.size
|
58
|
+
|
59
|
+
ENV["RUBY_GC_TUNE_REQUESTS"] = "2"
|
60
|
+
|
61
|
+
process_request
|
62
|
+
assert_equal 2, interposer.spy.subscriptions.size
|
63
|
+
process_request
|
64
|
+
assert_equal 0, interposer.spy.subscriptions.size
|
65
|
+
interposer.uninstall
|
66
|
+
ensure
|
67
|
+
ENV.delete("RUBY_GC_TUNE_REQUESTS")
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), 'helper')
|
4
|
+
|
5
|
+
class TestRailtie < TuneMyGcTestCase
|
6
|
+
def test_init
|
7
|
+
out, err = capture_io do
|
8
|
+
Rails.logger = Logger.new($stdout)
|
9
|
+
TuneMyGc::Railtie.run_initializers
|
10
|
+
sleep 1
|
11
|
+
end
|
12
|
+
assert_equal Rails.logger, TuneMyGc.logger
|
13
|
+
assert_match(/interposing/, out)
|
14
|
+
assert_match(/after_initialize/, out)
|
15
|
+
assert_match(/at_exit/, out)
|
16
|
+
assert_match(/interposed/, out)
|
17
|
+
ensure
|
18
|
+
TuneMyGc.logger = Logger.new($stdout)
|
19
|
+
TuneMyGc.interposer.uninstall
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), 'helper')
|
4
|
+
|
5
|
+
class TestSnapshotter < TuneMyGcTestCase
|
6
|
+
def test_init
|
7
|
+
snapshots = TuneMyGc::Snapshotter.new
|
8
|
+
assert_equal 0, snapshots.size
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_take
|
12
|
+
snapshots = TuneMyGc::Snapshotter.new
|
13
|
+
snapshots.take(:BOOTED)
|
14
|
+
assert_equal 1, snapshots.size
|
15
|
+
snapshots.clear
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_clear
|
19
|
+
snapshots = TuneMyGc::Snapshotter.new
|
20
|
+
snapshots.take(:BOOTED)
|
21
|
+
assert_equal 1, snapshots.size
|
22
|
+
snapshots.clear
|
23
|
+
assert_equal 0, snapshots.size
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_max_samples
|
27
|
+
snapshots = TuneMyGc::Snapshotter.new
|
28
|
+
1000.times do |i|
|
29
|
+
snapshots.take(:MAX)
|
30
|
+
end
|
31
|
+
assert_equal 1000, snapshots.size
|
32
|
+
out, err = capture_io do
|
33
|
+
TuneMyGc.logger = Logger.new($stdout)
|
34
|
+
snapshots.take(:MORE)
|
35
|
+
snapshots.take(:ANOTHER)
|
36
|
+
end
|
37
|
+
assert_match(/Discarding snapshot/, out)
|
38
|
+
assert_equal 1000, snapshots.size
|
39
|
+
snapshots.clear
|
40
|
+
end
|
41
|
+
end
|
data/test/test_syncer.rb
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), 'helper')
|
4
|
+
|
5
|
+
class TestSyncer < TuneMyGcTestCase
|
6
|
+
def test_uri
|
7
|
+
syncer = TuneMyGc::Syncer.new
|
8
|
+
assert_equal "tunemygc.com", syncer.uri.host
|
9
|
+
assert_equal 443, syncer.uri.port
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_client
|
13
|
+
syncer = TuneMyGc::Syncer.new
|
14
|
+
assert_instance_of Net::HTTP, syncer.client
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_environment
|
18
|
+
assert_equal 7, TuneMyGc::Syncer::ENVIRONMENT.size
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_sync_valid_snapshot
|
22
|
+
syncer = TuneMyGc::Syncer.new
|
23
|
+
snapshots = TuneMyGc::Snapshotter.new
|
24
|
+
snapshots.take_raw(Fixtures::STAGE_BOOTED)
|
25
|
+
|
26
|
+
stub_request(:get, "https://tunemygc.com/configs/xxxxxxx").
|
27
|
+
with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
|
28
|
+
to_return(:status => 200, :body => ActiveSupport::JSON.encode({:Memory=>{:RUBY_GC_HEAP_INIT_SLOTS=>477268, :RUBY_GC_HEAP_FREE_SLOTS=>106607, :RUBY_GC_HEAP_GROWTH_FACTOR=>1.05, :RUBY_GC_HEAP_GROWTH_MAX_SLOTS=>10661, :RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR=>1.05, :RUBY_GC_MALLOC_LIMIT=>2000000, :RUBY_GC_MALLOC_LIMIT_MAX=>4000000, :RUBY_GC_MALLOC_LIMIT_GROWTH_FACTOR=>1.1, :RUBY_GC_OLDMALLOC_LIMIT=>2000000, :RUBY_GC_OLDMALLOC_LIMIT_MAX=>4000000, :RUBY_GC_OLDMALLOC_LIMIT_GROWTH_FACTOR=>1.05}, :Speed=>{:RUBY_GC_HEAP_INIT_SLOTS=>572722, :RUBY_GC_HEAP_FREE_SLOTS=>553800, :RUBY_GC_HEAP_GROWTH_FACTOR=>1.2, :RUBY_GC_HEAP_GROWTH_MAX_SLOTS=>83070, :RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR=>2.0, :RUBY_GC_MALLOC_LIMIT=>64000000, :RUBY_GC_MALLOC_LIMIT_MAX=>128000000, :RUBY_GC_MALLOC_LIMIT_GROWTH_FACTOR=>1.56, :RUBY_GC_OLDMALLOC_LIMIT=>64000000, :RUBY_GC_OLDMALLOC_LIMIT_MAX=>33554432, :RUBY_GC_OLDMALLOC_LIMIT_GROWTH_FACTOR=>1.32}}), :headers => {})
|
29
|
+
|
30
|
+
stub_request(:post, "https://tunemygc.com/ruby").
|
31
|
+
with(:body => "[#{ActiveSupport::JSON.encode(TuneMyGc::Syncer::ENVIRONMENT)},[1420152606.1162581,\"BOOTED\",{\"count\":32,\"heap_used\":950,\"heap_length\":1519,\"heap_increment\":569,\"heap_live_slot\":385225,\"heap_free_slot\":2014,\"heap_final_slot\":0,\"heap_swept_slot\":101119,\"heap_eden_page_length\":950,\"heap_tomb_page_length\":0,\"total_allocated_object\":2184137,\"total_freed_object\":1798912,\"malloc_increase\":9665288,\"malloc_limit\":16777216,\"minor_gc_count\":26,\"major_gc_count\":6,\"remembered_shady_object\":5145,\"remembered_shady_object_limit\":6032,\"old_object\":230164,\"old_object_limit\":301030,\"oldmalloc_increase\":11715304,\"oldmalloc_limit\":24159190},{\"major_by\":null,\"gc_by\":\"newobj\",\"have_finalizer\":false,\"immediate_sweep\":false},null]]",
|
32
|
+
:headers => {'Accept'=>'application/json', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type'=>'application/json', 'User-Agent'=>'TuneMyGC 1.0'}).
|
33
|
+
to_return(:status => 200, :body => "https://www.tunemygc.com/configs/xxxxxxx", :headers => {})
|
34
|
+
|
35
|
+
out, err = capture_io do
|
36
|
+
TuneMyGc.logger = Logger.new($stdout)
|
37
|
+
assert syncer.sync(snapshots)
|
38
|
+
#s = syncer.sync(snapshots)
|
39
|
+
#assert s
|
40
|
+
end
|
41
|
+
assert_match(/Syncing 1 snapshots/, out)
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_not_supported
|
45
|
+
syncer = TuneMyGc::Syncer.new
|
46
|
+
snapshots = TuneMyGc::Snapshotter.new
|
47
|
+
snapshots.take_raw(Fixtures::STAGE_BOOTED)
|
48
|
+
stub_request(:post, "https://tunemygc.com/ruby").
|
49
|
+
with(:body => "[#{ActiveSupport::JSON.encode(TuneMyGc::Syncer::ENVIRONMENT)},[1420152606.1162581,\"BOOTED\",{\"count\":32,\"heap_used\":950,\"heap_length\":1519,\"heap_increment\":569,\"heap_live_slot\":385225,\"heap_free_slot\":2014,\"heap_final_slot\":0,\"heap_swept_slot\":101119,\"heap_eden_page_length\":950,\"heap_tomb_page_length\":0,\"total_allocated_object\":2184137,\"total_freed_object\":1798912,\"malloc_increase\":9665288,\"malloc_limit\":16777216,\"minor_gc_count\":26,\"major_gc_count\":6,\"remembered_shady_object\":5145,\"remembered_shady_object_limit\":6032,\"old_object\":230164,\"old_object_limit\":301030,\"oldmalloc_increase\":11715304,\"oldmalloc_limit\":24159190},{\"major_by\":null,\"gc_by\":\"newobj\",\"have_finalizer\":false,\"immediate_sweep\":false},null]]",
|
50
|
+
:headers => {'Accept'=>'application/json', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type'=>'application/json', 'User-Agent'=>'TuneMyGC 1.0'}).
|
51
|
+
to_return(:status => 501, :body => "", :headers => {})
|
52
|
+
|
53
|
+
out, err = capture_io do
|
54
|
+
TuneMyGc.logger = Logger.new($stdout)
|
55
|
+
assert_nil syncer.sync(snapshots)
|
56
|
+
end
|
57
|
+
assert_match(/Ruby version/, out)
|
58
|
+
assert_match(/Rails version/, out)
|
59
|
+
assert_match(/not supported/, out)
|
60
|
+
assert_match(/Failed to sync 1 snapshots/, out)
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_already_configured
|
64
|
+
syncer = TuneMyGc::Syncer.new
|
65
|
+
snapshots = TuneMyGc::Snapshotter.new
|
66
|
+
snapshots.take_raw(Fixtures::STAGE_BOOTED)
|
67
|
+
stub_request(:post, "https://tunemygc.com/ruby").
|
68
|
+
with(:body => "[#{ActiveSupport::JSON.encode(TuneMyGc::Syncer::ENVIRONMENT)},[1420152606.1162581,\"BOOTED\",{\"count\":32,\"heap_used\":950,\"heap_length\":1519,\"heap_increment\":569,\"heap_live_slot\":385225,\"heap_free_slot\":2014,\"heap_final_slot\":0,\"heap_swept_slot\":101119,\"heap_eden_page_length\":950,\"heap_tomb_page_length\":0,\"total_allocated_object\":2184137,\"total_freed_object\":1798912,\"malloc_increase\":9665288,\"malloc_limit\":16777216,\"minor_gc_count\":26,\"major_gc_count\":6,\"remembered_shady_object\":5145,\"remembered_shady_object_limit\":6032,\"old_object\":230164,\"old_object_limit\":301030,\"oldmalloc_increase\":11715304,\"oldmalloc_limit\":24159190},{\"major_by\":null,\"gc_by\":\"newobj\",\"have_finalizer\":false,\"immediate_sweep\":false},null]]",
|
69
|
+
:headers => {'Accept'=>'application/json', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type'=>'application/json', 'User-Agent'=>'TuneMyGC 1.0'}).
|
70
|
+
to_return(:status => 412, :body => "", :headers => {})
|
71
|
+
|
72
|
+
out, err = capture_io do
|
73
|
+
TuneMyGc.logger = Logger.new($stdout)
|
74
|
+
assert_nil syncer.sync(snapshots)
|
75
|
+
end
|
76
|
+
assert_match(/The GC is already tuned by environment variables/, out)
|
77
|
+
assert_match(/Failed to sync 1 snapshots/, out)
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_bad_payload
|
81
|
+
syncer = TuneMyGc::Syncer.new
|
82
|
+
snapshots = TuneMyGc::Snapshotter.new
|
83
|
+
snapshots.take_raw(Fixtures::STAGE_BOOTED)
|
84
|
+
stub_request(:post, "https://tunemygc.com/ruby").
|
85
|
+
with(:body => "[#{ActiveSupport::JSON.encode(TuneMyGc::Syncer::ENVIRONMENT)},[1420152606.1162581,\"BOOTED\",{\"count\":32,\"heap_used\":950,\"heap_length\":1519,\"heap_increment\":569,\"heap_live_slot\":385225,\"heap_free_slot\":2014,\"heap_final_slot\":0,\"heap_swept_slot\":101119,\"heap_eden_page_length\":950,\"heap_tomb_page_length\":0,\"total_allocated_object\":2184137,\"total_freed_object\":1798912,\"malloc_increase\":9665288,\"malloc_limit\":16777216,\"minor_gc_count\":26,\"major_gc_count\":6,\"remembered_shady_object\":5145,\"remembered_shady_object_limit\":6032,\"old_object\":230164,\"old_object_limit\":301030,\"oldmalloc_increase\":11715304,\"oldmalloc_limit\":24159190},{\"major_by\":null,\"gc_by\":\"newobj\",\"have_finalizer\":false,\"immediate_sweep\":false},null]]",
|
86
|
+
:headers => {'Accept'=>'application/json', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type'=>'application/json', 'User-Agent'=>'TuneMyGC 1.0'}).
|
87
|
+
to_return(:status => 400, :body => "snapshot timestamp", :headers => {})
|
88
|
+
|
89
|
+
out, err = capture_io do
|
90
|
+
TuneMyGc.logger = Logger.new($stdout)
|
91
|
+
assert_nil syncer.sync(snapshots)
|
92
|
+
end
|
93
|
+
assert_match(/Invalid payload/, out)
|
94
|
+
assert_match(/snapshot timestamp/, out)
|
95
|
+
assert_match(/Failed to sync 1 snapshots/, out)
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_invalid_token
|
99
|
+
syncer = TuneMyGc::Syncer.new
|
100
|
+
snapshots = TuneMyGc::Snapshotter.new
|
101
|
+
snapshots.take_raw(Fixtures::STAGE_BOOTED)
|
102
|
+
stub_request(:post, "https://tunemygc.com/ruby").
|
103
|
+
with(:body => "[#{ActiveSupport::JSON.encode(TuneMyGc::Syncer::ENVIRONMENT)},[1420152606.1162581,\"BOOTED\",{\"count\":32,\"heap_used\":950,\"heap_length\":1519,\"heap_increment\":569,\"heap_live_slot\":385225,\"heap_free_slot\":2014,\"heap_final_slot\":0,\"heap_swept_slot\":101119,\"heap_eden_page_length\":950,\"heap_tomb_page_length\":0,\"total_allocated_object\":2184137,\"total_freed_object\":1798912,\"malloc_increase\":9665288,\"malloc_limit\":16777216,\"minor_gc_count\":26,\"major_gc_count\":6,\"remembered_shady_object\":5145,\"remembered_shady_object_limit\":6032,\"old_object\":230164,\"old_object_limit\":301030,\"oldmalloc_increase\":11715304,\"oldmalloc_limit\":24159190},{\"major_by\":null,\"gc_by\":\"newobj\",\"have_finalizer\":false,\"immediate_sweep\":false},null]]",
|
104
|
+
:headers => {'Accept'=>'application/json', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type'=>'application/json', 'User-Agent'=>'TuneMyGC 1.0'}).
|
105
|
+
to_return(:status => 404, :body => "", :headers => {})
|
106
|
+
|
107
|
+
out, err = capture_io do
|
108
|
+
TuneMyGc.logger = Logger.new($stdout)
|
109
|
+
assert_nil syncer.sync(snapshots)
|
110
|
+
end
|
111
|
+
assert_match(/Invalid application token/, out)
|
112
|
+
end
|
113
|
+
|
114
|
+
def test_upgrade_required
|
115
|
+
syncer = TuneMyGc::Syncer.new
|
116
|
+
snapshots = TuneMyGc::Snapshotter.new
|
117
|
+
snapshots.take_raw(Fixtures::STAGE_BOOTED)
|
118
|
+
stub_request(:post, "https://tunemygc.com/ruby").
|
119
|
+
with(:body => "[#{ActiveSupport::JSON.encode(TuneMyGc::Syncer::ENVIRONMENT)},[1420152606.1162581,\"BOOTED\",{\"count\":32,\"heap_used\":950,\"heap_length\":1519,\"heap_increment\":569,\"heap_live_slot\":385225,\"heap_free_slot\":2014,\"heap_final_slot\":0,\"heap_swept_slot\":101119,\"heap_eden_page_length\":950,\"heap_tomb_page_length\":0,\"total_allocated_object\":2184137,\"total_freed_object\":1798912,\"malloc_increase\":9665288,\"malloc_limit\":16777216,\"minor_gc_count\":26,\"major_gc_count\":6,\"remembered_shady_object\":5145,\"remembered_shady_object_limit\":6032,\"old_object\":230164,\"old_object_limit\":301030,\"oldmalloc_increase\":11715304,\"oldmalloc_limit\":24159190},{\"major_by\":null,\"gc_by\":\"newobj\",\"have_finalizer\":false,\"immediate_sweep\":false},null]]",
|
120
|
+
:headers => {'Accept'=>'application/json', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type'=>'application/json', 'User-Agent'=>'TuneMyGC 1.0'}).
|
121
|
+
to_return(:status => 426, :body => "2", :headers => {})
|
122
|
+
|
123
|
+
out, err = capture_io do
|
124
|
+
TuneMyGc.logger = Logger.new($stdout)
|
125
|
+
assert_nil syncer.sync(snapshots)
|
126
|
+
end
|
127
|
+
assert_match(/Agent version 2 required/, out)
|
128
|
+
assert_match(/Failed to sync 1 snapshots/, out)
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_sync_error
|
132
|
+
syncer = TuneMyGc::Syncer.new
|
133
|
+
snapshots = TuneMyGc::Snapshotter.new
|
134
|
+
snapshots.take_raw(Fixtures::STAGE_BOOTED)
|
135
|
+
stub_request(:post, "https://tunemygc.com/ruby").
|
136
|
+
with(:body => "[#{ActiveSupport::JSON.encode(TuneMyGc::Syncer::ENVIRONMENT)},[1420152606.1162581,\"BOOTED\",{\"count\":32,\"heap_used\":950,\"heap_length\":1519,\"heap_increment\":569,\"heap_live_slot\":385225,\"heap_free_slot\":2014,\"heap_final_slot\":0,\"heap_swept_slot\":101119,\"heap_eden_page_length\":950,\"heap_tomb_page_length\":0,\"total_allocated_object\":2184137,\"total_freed_object\":1798912,\"malloc_increase\":9665288,\"malloc_limit\":16777216,\"minor_gc_count\":26,\"major_gc_count\":6,\"remembered_shady_object\":5145,\"remembered_shady_object_limit\":6032,\"old_object\":230164,\"old_object_limit\":301030,\"oldmalloc_increase\":11715304,\"oldmalloc_limit\":24159190},{\"major_by\":null,\"gc_by\":\"newobj\",\"have_finalizer\":false,\"immediate_sweep\":false},null]]",
|
137
|
+
:headers => {'Accept'=>'application/json', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type'=>'application/json', 'User-Agent'=>'TuneMyGC 1.0'}).to_raise(IOError.new("dang"))
|
138
|
+
|
139
|
+
out, err = capture_io do
|
140
|
+
TuneMyGc.logger = Logger.new($stdout)
|
141
|
+
assert_nil syncer.sync(snapshots)
|
142
|
+
end
|
143
|
+
assert_match(/Failed to sync 1 snapshots/, out)
|
144
|
+
assert_match(/dang/, out)
|
145
|
+
end
|
146
|
+
end
|
data/tunemygc-1.0.gem
ADDED
Binary file
|
data/tunemygc.gemspec
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
lib = File.expand_path('../lib', __FILE__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require 'tunemygc/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |s|
|
8
|
+
s.name = "tunemygc"
|
9
|
+
s.version = TuneMyGc::VERSION
|
10
|
+
s.summary = "TuneMyGC - optimal MRI Ruby 2.1+ Garbage Collection"
|
11
|
+
s.description = "Agent for the GC tuning webservice https://www.tunemygc.com - optimal settings for throughput and memory usage of Rails applications"
|
12
|
+
s.authors = ["Bear Metal OÜ"]
|
13
|
+
s.email = ["info@bearmetal.eu"]
|
14
|
+
s.license = "MIT"
|
15
|
+
s.homepage = "https://tunemygc.com"
|
16
|
+
s.date = Time.now.utc.strftime('%Y-%m-%d')
|
17
|
+
s.platform = Gem::Platform::RUBY
|
18
|
+
s.files = `git ls-files`.split($/)
|
19
|
+
s.executables = s.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
20
|
+
s.extensions = "ext/tunemygc/extconf.rb"
|
21
|
+
s.test_files = `git ls-files test`.split($/)
|
22
|
+
s.require_paths = ["lib"]
|
23
|
+
s.required_ruby_version = '>= 2.1.0'
|
24
|
+
s.post_install_message = <<-eos
|
25
|
+
[TuneMyGC] Getting started:
|
26
|
+
|
27
|
+
Run this setup command from your application root to register your application with the `https://tunemygc.com` service:
|
28
|
+
|
29
|
+
bundle exec tunemygc -r your@email.address
|
30
|
+
|
31
|
+
You should get back a token reference to identify this Rails app:
|
32
|
+
|
33
|
+
Application registered. Use RUBY_GC_TOKEN=08de9e8822c847244b31290cedfc1d32 in your environment.
|
34
|
+
|
35
|
+
Then sample your Rails app for tuning:
|
36
|
+
|
37
|
+
RUBY_GC_TOKEN=08de9e8822c847244b31290cedfc1d32 RUBY_GC_TUNE=1 bundle exec rails s
|
38
|
+
|
39
|
+
We require a valid email address as a canonical reference for tuner tokens for your applications.
|
40
|
+
|
41
|
+
Happy hacking,
|
42
|
+
- the Bear Metal cubs
|
43
|
+
eos
|
44
|
+
|
45
|
+
s.add_dependency('activesupport', '~> 4.1')
|
46
|
+
s.add_dependency('certified', '~> 1.0', '>= 1.0.0')
|
47
|
+
s.add_development_dependency('rake', '~> 10.3')
|
48
|
+
s.add_development_dependency('rake-compiler', '~> 0.9', '>= 0.9.5')
|
49
|
+
s.add_development_dependency('webmock', '~> 1.2', '>= 1.2.0')
|
50
|
+
end
|
metadata
ADDED
@@ -0,0 +1,194 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tunemygc
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Bear Metal OÜ
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-01-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: certified
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.0'
|
34
|
+
- - ">="
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: 1.0.0
|
37
|
+
type: :runtime
|
38
|
+
prerelease: false
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - "~>"
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '1.0'
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 1.0.0
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rake
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '10.3'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '10.3'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: rake-compiler
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0.9'
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: 0.9.5
|
71
|
+
type: :development
|
72
|
+
prerelease: false
|
73
|
+
version_requirements: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - "~>"
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0.9'
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: 0.9.5
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: webmock
|
83
|
+
requirement: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - "~>"
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '1.2'
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: 1.2.0
|
91
|
+
type: :development
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - "~>"
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '1.2'
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: 1.2.0
|
101
|
+
description: Agent for the GC tuning webservice https://www.tunemygc.com - optimal
|
102
|
+
settings for throughput and memory usage of Rails applications
|
103
|
+
email:
|
104
|
+
- info@bearmetal.eu
|
105
|
+
executables:
|
106
|
+
- tunemygc
|
107
|
+
extensions:
|
108
|
+
- ext/tunemygc/extconf.rb
|
109
|
+
extra_rdoc_files: []
|
110
|
+
files:
|
111
|
+
- ".gitignore"
|
112
|
+
- ".travis.yml"
|
113
|
+
- Gemfile
|
114
|
+
- Gemfile.lock
|
115
|
+
- README.md
|
116
|
+
- Rakefile
|
117
|
+
- assets/discourse_bench.png
|
118
|
+
- assets/tunemygc-graphic2x-80dac1571cacc70d9b272bb62ae9f6df.png
|
119
|
+
- bin/tunemygc
|
120
|
+
- ext/tunemygc/extconf.rb
|
121
|
+
- ext/tunemygc/getRSS.c
|
122
|
+
- ext/tunemygc/tunemygc_ext.c
|
123
|
+
- ext/tunemygc/tunemygc_ext.h
|
124
|
+
- lib/tunemygc.rb
|
125
|
+
- lib/tunemygc/agent.rb
|
126
|
+
- lib/tunemygc/cli.rb
|
127
|
+
- lib/tunemygc/configurator.rb
|
128
|
+
- lib/tunemygc/interposer.rb
|
129
|
+
- lib/tunemygc/railtie.rb
|
130
|
+
- lib/tunemygc/request_subscriber.rb
|
131
|
+
- lib/tunemygc/snapshotter.rb
|
132
|
+
- lib/tunemygc/spies/action_controller.rb
|
133
|
+
- lib/tunemygc/subscriber.rb
|
134
|
+
- lib/tunemygc/syncer.rb
|
135
|
+
- lib/tunemygc/version.rb
|
136
|
+
- test/fixtures.rb
|
137
|
+
- test/helper.rb
|
138
|
+
- test/test_agent.rb
|
139
|
+
- test/test_interposer.rb
|
140
|
+
- test/test_railtie.rb
|
141
|
+
- test/test_snapshotter.rb
|
142
|
+
- test/test_syncer.rb
|
143
|
+
- tunemygc-1.0.gem
|
144
|
+
- tunemygc.gemspec
|
145
|
+
homepage: https://tunemygc.com
|
146
|
+
licenses:
|
147
|
+
- MIT
|
148
|
+
metadata: {}
|
149
|
+
post_install_message: |2
|
150
|
+
[TuneMyGC] Getting started:
|
151
|
+
|
152
|
+
Run this setup command from your application root to register your application with the `https://tunemygc.com` service:
|
153
|
+
|
154
|
+
bundle exec tunemygc -r your@email.address
|
155
|
+
|
156
|
+
You should get back a token reference to identify this Rails app:
|
157
|
+
|
158
|
+
Application registered. Use RUBY_GC_TOKEN=08de9e8822c847244b31290cedfc1d32 in your environment.
|
159
|
+
|
160
|
+
Then sample your Rails app for tuning:
|
161
|
+
|
162
|
+
RUBY_GC_TOKEN=08de9e8822c847244b31290cedfc1d32 RUBY_GC_TUNE=1 bundle exec rails s
|
163
|
+
|
164
|
+
We require a valid email address as a canonical reference for tuner tokens for your applications.
|
165
|
+
|
166
|
+
Happy hacking,
|
167
|
+
- the Bear Metal cubs
|
168
|
+
rdoc_options: []
|
169
|
+
require_paths:
|
170
|
+
- lib
|
171
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
172
|
+
requirements:
|
173
|
+
- - ">="
|
174
|
+
- !ruby/object:Gem::Version
|
175
|
+
version: 2.1.0
|
176
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
181
|
+
requirements: []
|
182
|
+
rubyforge_project:
|
183
|
+
rubygems_version: 2.2.2
|
184
|
+
signing_key:
|
185
|
+
specification_version: 4
|
186
|
+
summary: TuneMyGC - optimal MRI Ruby 2.1+ Garbage Collection
|
187
|
+
test_files:
|
188
|
+
- test/fixtures.rb
|
189
|
+
- test/helper.rb
|
190
|
+
- test/test_agent.rb
|
191
|
+
- test/test_interposer.rb
|
192
|
+
- test/test_railtie.rb
|
193
|
+
- test/test_snapshotter.rb
|
194
|
+
- test/test_syncer.rb
|