rmemlimit 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.
- data/CHANGELOG +1 -0
- data/Manifest +6 -0
- data/README.md +37 -0
- data/Rakefile +8 -0
- data/lib/rmemlimit.rb +55 -0
- data/rmemlimit.gemspec +30 -0
- data/test/test_all.rb +28 -0
- metadata +61 -0
data/CHANGELOG
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
v0.1. Proof of concept
|
data/Manifest
ADDED
data/README.md
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
|
2
|
+
## Rmemlimit gem
|
3
|
+
|
4
|
+
The garbage collector in Ruby 1.x is blocking, and runs whenever there is a
|
5
|
+
need to allocate more memory for new objects.
|
6
|
+
|
7
|
+
In a large application (eg. Rails) it runs many times per second, saving
|
8
|
+
memory but hurting performance.
|
9
|
+
|
10
|
+
#### Run GC less often
|
11
|
+
|
12
|
+
To increase performance, you can use this gem to run the GC once per second
|
13
|
+
instead, in a background thread.
|
14
|
+
|
15
|
+
gem 'rmemlimit' # in your Gemfile
|
16
|
+
|
17
|
+
|
18
|
+
#### Set a memory limit for GC (requires linux /proc)
|
19
|
+
|
20
|
+
If you know roughly how much RAM you want your app to use, you can set that
|
21
|
+
and GC will run whenever it is exceeded. Resident Set Size is checked once
|
22
|
+
per second. Example to limit to 500MB:
|
23
|
+
|
24
|
+
Rmemlimit.gc_mb = 500
|
25
|
+
|
26
|
+
(Or you can use the RUBY_GC_MB environment variable).
|
27
|
+
|
28
|
+
|
29
|
+
#### Set a hard memory limit for Ruby
|
30
|
+
|
31
|
+
If your application sometimes eats too much memory and you'd rather have it
|
32
|
+
kill itself when it passes a threshold, you can do limit to say 1000MB:
|
33
|
+
|
34
|
+
Rmemlimit.kill_mb = 1000
|
35
|
+
|
36
|
+
(Or you can use the RUBY_KILL_MB environment variable)
|
37
|
+
|
data/Rakefile
ADDED
data/lib/rmemlimit.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
|
2
|
+
class Rmemlimit
|
3
|
+
|
4
|
+
class << self
|
5
|
+
attr_accessor :gc_mb, :kill_mb
|
6
|
+
|
7
|
+
def gcthread
|
8
|
+
@gcthread ||= Thread.new do
|
9
|
+
loop do
|
10
|
+
mb = rss_mb
|
11
|
+
if kill_mb && mb > kill_mb
|
12
|
+
STDERR.puts "#{self}: Exceeded kill memory limit (#{mb} > #{kill_Mb} MB)"
|
13
|
+
Process.kill(9, $$)
|
14
|
+
elsif gc_mb && mb > gc_mb
|
15
|
+
run_gc
|
16
|
+
elsif mb == 0 || !gc_mb || !kill_mb
|
17
|
+
run_gc
|
18
|
+
end
|
19
|
+
sleep 1
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def run_gc
|
25
|
+
GC.enable
|
26
|
+
GC.start
|
27
|
+
GC.disable
|
28
|
+
end
|
29
|
+
|
30
|
+
def pagesize
|
31
|
+
4096
|
32
|
+
end
|
33
|
+
|
34
|
+
def rss_mb
|
35
|
+
rss_kb >> 10
|
36
|
+
end
|
37
|
+
|
38
|
+
def rss_kb
|
39
|
+
pagesize * (File.read("/proc/#{$$}/statm").split(' ')[1].to_i rescue 0) >> 10
|
40
|
+
end
|
41
|
+
|
42
|
+
def setup
|
43
|
+
self.gc_mb = ENV['RUBY_GC_MB'].to_i if ENV['RUBY_GC_MB']
|
44
|
+
if ENV['RUBY_KILL_MB']
|
45
|
+
self.kill_mb = ENV['RUBY_KILL_MB'].to_i
|
46
|
+
self.kill_mb = nil unless Rmemlimit.kill_mb > 1
|
47
|
+
end
|
48
|
+
GC.disable
|
49
|
+
self.gcthread
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
Rmemlimit.setup
|
data/rmemlimit.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = "rmemlimit"
|
5
|
+
s.version = "0.1"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Andrew Snow"]
|
9
|
+
s.date = "2012-12-28"
|
10
|
+
s.description = "Slow down garbage collector & limit ruby process memory"
|
11
|
+
s.email = "andrew@modulus.org"
|
12
|
+
s.extra_rdoc_files = ["CHANGELOG", "README.md", "lib/rmemlimit.rb"]
|
13
|
+
s.files = ["CHANGELOG", "README.md", "Rakefile", "lib/rmemlimit.rb", "test/test_all.rb", "Manifest", "rmemlimit.gemspec"]
|
14
|
+
s.homepage = "https://github.com/andys/rmemlimit"
|
15
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Rmemlimit", "--main", "README.md"]
|
16
|
+
s.require_paths = ["lib"]
|
17
|
+
s.rubyforge_project = "rmemlimit"
|
18
|
+
s.rubygems_version = "1.8.24"
|
19
|
+
s.summary = "Slow down garbage collector & limit ruby process memory"
|
20
|
+
s.test_files = ["test/test_all.rb"]
|
21
|
+
|
22
|
+
if s.respond_to? :specification_version then
|
23
|
+
s.specification_version = 3
|
24
|
+
|
25
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
26
|
+
else
|
27
|
+
end
|
28
|
+
else
|
29
|
+
end
|
30
|
+
end
|
data/test/test_all.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/../lib/rmemlimit"
|
2
|
+
require 'test/unit'
|
3
|
+
|
4
|
+
class TestRmemlimit < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def test_rss_kb
|
7
|
+
kb = Rmemlimit.rss_kb
|
8
|
+
assert(kb > 0)
|
9
|
+
|
10
|
+
assert_equal "VmRSS:\t%8d kB\n" % kb,
|
11
|
+
File.read("/proc/#{$$}/status").lines.grep(/VmRSS/).first
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_run_gc
|
15
|
+
gccount = GC.stat[:count] + 1
|
16
|
+
sleep 1.1
|
17
|
+
assert_equal gccount, GC.stat[:count]
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_gc_mb
|
21
|
+
Rmemlimit.gc_mb = Rmemlimit.rss_mb
|
22
|
+
gccount = GC.stat[:count] + 1
|
23
|
+
flibble = 'x' * 1024 * 1024
|
24
|
+
sleep 1.1
|
25
|
+
assert_equal gccount, GC.stat[:count]
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rmemlimit
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: '0.1'
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Andrew Snow
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-12-28 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Slow down garbage collector & limit ruby process memory
|
15
|
+
email: andrew@modulus.org
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files:
|
19
|
+
- CHANGELOG
|
20
|
+
- README.md
|
21
|
+
- lib/rmemlimit.rb
|
22
|
+
files:
|
23
|
+
- CHANGELOG
|
24
|
+
- README.md
|
25
|
+
- Rakefile
|
26
|
+
- lib/rmemlimit.rb
|
27
|
+
- test/test_all.rb
|
28
|
+
- Manifest
|
29
|
+
- rmemlimit.gemspec
|
30
|
+
homepage: https://github.com/andys/rmemlimit
|
31
|
+
licenses: []
|
32
|
+
post_install_message:
|
33
|
+
rdoc_options:
|
34
|
+
- --line-numbers
|
35
|
+
- --inline-source
|
36
|
+
- --title
|
37
|
+
- Rmemlimit
|
38
|
+
- --main
|
39
|
+
- README.md
|
40
|
+
require_paths:
|
41
|
+
- lib
|
42
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ! '>='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
none: false
|
48
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ! '>='
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '1.2'
|
53
|
+
none: false
|
54
|
+
requirements: []
|
55
|
+
rubyforge_project: rmemlimit
|
56
|
+
rubygems_version: 1.8.24
|
57
|
+
signing_key:
|
58
|
+
specification_version: 3
|
59
|
+
summary: Slow down garbage collector & limit ruby process memory
|
60
|
+
test_files:
|
61
|
+
- test/test_all.rb
|