tunemygc 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4401c1469c2636840a42026092dcd8d682d8825f
4
+ data.tar.gz: 5e44ddbc6336a4683b155393087bc8d39bc95cba
5
+ SHA512:
6
+ metadata.gz: 294670fabab8fa5203a580b6a4182ebb888d83d52710dfe8f82fb5545b6daefdeb3dad21d72c16b7bc2c6f0f0b3cc5ccd73d65bac3512468dd1c383f21a58568
7
+ data.tar.gz: 6bac1f88cad71533a4731332526dabc49e3b60b2d77c68a133dc7b6dea55ade00b8522cf372b2884777f572744028e70f59435303e27ac1ebfb1c3c8ad88f760
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ .DS_Store
2
+ .ruby-version
3
+ tmp/*
4
+ lib/tunemygc/tunemygc_ext.*
data/.travis.yml ADDED
@@ -0,0 +1,19 @@
1
+ language: ruby
2
+ bundler_args: --quiet
3
+ rvm:
4
+ - 2.1.0
5
+ - 2.1.1
6
+ - 2.1.2
7
+ - 2.1.5
8
+ - 2.2.0
9
+ - ruby-head
10
+ script: "bundle exec rake"
11
+ env: RUBY_GC_TUNE=1 RUBY_GC_TUNE_DEBUG=1
12
+ gemfile:
13
+ - Gemfile
14
+ notifications:
15
+ recipients:
16
+ - lourens@methodmissing.com
17
+ branches:
18
+ only:
19
+ - master
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem 'rails'
data/Gemfile.lock ADDED
@@ -0,0 +1,125 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ tunemygc (1.0)
5
+ activesupport
6
+ certified
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ actionmailer (4.2.0)
12
+ actionpack (= 4.2.0)
13
+ actionview (= 4.2.0)
14
+ activejob (= 4.2.0)
15
+ mail (~> 2.5, >= 2.5.4)
16
+ rails-dom-testing (~> 1.0, >= 1.0.5)
17
+ actionpack (4.2.0)
18
+ actionview (= 4.2.0)
19
+ activesupport (= 4.2.0)
20
+ rack (~> 1.6.0)
21
+ rack-test (~> 0.6.2)
22
+ rails-dom-testing (~> 1.0, >= 1.0.5)
23
+ rails-html-sanitizer (~> 1.0, >= 1.0.1)
24
+ actionview (4.2.0)
25
+ activesupport (= 4.2.0)
26
+ builder (~> 3.1)
27
+ erubis (~> 2.7.0)
28
+ rails-dom-testing (~> 1.0, >= 1.0.5)
29
+ rails-html-sanitizer (~> 1.0, >= 1.0.1)
30
+ activejob (4.2.0)
31
+ activesupport (= 4.2.0)
32
+ globalid (>= 0.3.0)
33
+ activemodel (4.2.0)
34
+ activesupport (= 4.2.0)
35
+ builder (~> 3.1)
36
+ activerecord (4.2.0)
37
+ activemodel (= 4.2.0)
38
+ activesupport (= 4.2.0)
39
+ arel (~> 6.0)
40
+ activesupport (4.2.0)
41
+ i18n (~> 0.7)
42
+ json (~> 1.7, >= 1.7.7)
43
+ minitest (~> 5.1)
44
+ thread_safe (~> 0.3, >= 0.3.4)
45
+ tzinfo (~> 1.1)
46
+ addressable (2.3.6)
47
+ arel (6.0.0)
48
+ builder (3.2.2)
49
+ certified (1.0.0)
50
+ crack (0.4.2)
51
+ safe_yaml (~> 1.0.0)
52
+ erubis (2.7.0)
53
+ globalid (0.3.0)
54
+ activesupport (>= 4.1.0)
55
+ hike (1.2.3)
56
+ i18n (0.7.0)
57
+ json (1.8.2)
58
+ loofah (2.0.1)
59
+ nokogiri (>= 1.5.9)
60
+ mail (2.6.3)
61
+ mime-types (>= 1.16, < 3)
62
+ mime-types (2.4.3)
63
+ mini_portile (0.6.2)
64
+ minitest (5.5.0)
65
+ multi_json (1.10.1)
66
+ nokogiri (1.6.5)
67
+ mini_portile (~> 0.6.0)
68
+ rack (1.6.0)
69
+ rack-test (0.6.2)
70
+ rack (>= 1.0)
71
+ rails (4.2.0)
72
+ actionmailer (= 4.2.0)
73
+ actionpack (= 4.2.0)
74
+ actionview (= 4.2.0)
75
+ activejob (= 4.2.0)
76
+ activemodel (= 4.2.0)
77
+ activerecord (= 4.2.0)
78
+ activesupport (= 4.2.0)
79
+ bundler (>= 1.3.0, < 2.0)
80
+ railties (= 4.2.0)
81
+ sprockets-rails
82
+ rails-deprecated_sanitizer (1.0.3)
83
+ activesupport (>= 4.2.0.alpha)
84
+ rails-dom-testing (1.0.5)
85
+ activesupport (>= 4.2.0.beta, < 5.0)
86
+ nokogiri (~> 1.6.0)
87
+ rails-deprecated_sanitizer (>= 1.0.1)
88
+ rails-html-sanitizer (1.0.1)
89
+ loofah (~> 2.0)
90
+ railties (4.2.0)
91
+ actionpack (= 4.2.0)
92
+ activesupport (= 4.2.0)
93
+ rake (>= 0.8.7)
94
+ thor (>= 0.18.1, < 2.0)
95
+ rake (10.4.2)
96
+ rake-compiler (0.9.5)
97
+ rake
98
+ safe_yaml (1.0.4)
99
+ sprockets (2.12.3)
100
+ hike (~> 1.2)
101
+ multi_json (~> 1.0)
102
+ rack (~> 1.0)
103
+ tilt (~> 1.1, != 1.3.0)
104
+ sprockets-rails (2.2.2)
105
+ actionpack (>= 3.0)
106
+ activesupport (>= 3.0)
107
+ sprockets (>= 2.8, < 4.0)
108
+ thor (0.19.1)
109
+ thread_safe (0.3.4)
110
+ tilt (1.4.1)
111
+ tzinfo (1.2.2)
112
+ thread_safe (~> 0.1)
113
+ webmock (1.20.4)
114
+ addressable (>= 2.3.6)
115
+ crack (>= 0.3.2)
116
+
117
+ PLATFORMS
118
+ ruby
119
+
120
+ DEPENDENCIES
121
+ rails
122
+ rake
123
+ rake-compiler (~> 0.9.3)
124
+ tunemygc!
125
+ webmock
data/README.md ADDED
@@ -0,0 +1,193 @@
1
+ ## [TuneMyGC](https://www.tunemygc.com) - optimal MRI Ruby 2.1+ Garbage Collection
2
+
3
+ [![Build Status](https://travis-ci.org/bear-metal/tunemygc.svg)](https://travis-ci.org/bear-metal/tunemygc)
4
+
5
+ The Ruby garbage collector has been flagged as the crux of Ruby performance and memory use for a long time. It has improved a lot over the last years, but there's still a lot to tune and control. *The default configuration is not suitable and optimal for Rails applications, and neither is there a one-size-fits-all set of tuned parameters that would suit every app.* However, hand-tuning the GC parameters is a slippery slope to navigate for most developers.
6
+
7
+ ## We're fixing this
8
+
9
+ ![tunemygc workflow diagram](https://raw.githubusercontent.com/bear-metal/tunemygc/master/assets/tunemygc-graphic2x-80dac1571cacc70d9b272bb62ae9f6df.png?token=AAABe8sM_ofiQkrCpNw7OYRbtHMLO9l5ks5UuQlYwA%3D%3D)
10
+
11
+ ## Benefits
12
+
13
+ * Faster boot times
14
+ * Less major GC cycles during requests
15
+ * Less worst case memory usage - it's bound by sensible upper limits and growth factors
16
+ * No need to keep up to date with the C Ruby GC as an evolving moving target
17
+ * [in progress] A repeatable process to infer an optimal GC config for that app's current state within the context of a longer development cycle.
18
+
19
+ ## Benchmarks
20
+
21
+ We used [Discourse](http://www.discourse.org) as our primary test harness as it's representative of most Rails applications and has been instrumental in asserting RGenC developments on Rails as well.
22
+
23
+ ![tunemygc workflow diagram](https://raw.githubusercontent.com/bear-metal/tunemygc/master/assets/discourse_bench.png?token=AAABe8sM_ofiQkrCpNw7OYRbtHMLO9l5ks5UuQlYwA%3D%3D)
24
+
25
+ ## Installing
26
+
27
+ #### OS X / Linux
28
+
29
+ Add to your Gemfile and run `bundle install`
30
+
31
+ ``` sh
32
+ gem 'tunemygc', :require => 'tunemygc'
33
+ ```
34
+ This gem linterposes itself into the Rails request/response lifecycles and piggy backs off the new GC events in Ruby 2.x for introspection. Tuning recommendations are handled through a web service at `https://tunemygc.com`. You will need a `rails > 4.1`, installation and MRI Ruby `2.1`, or later.
35
+
36
+ #### Windows
37
+
38
+ Has not been tested at all.
39
+
40
+ ## Getting started
41
+
42
+ There isn't much setup other than adding the gem to your Gemfile and running a single command from your application root to register your application with the `https://tunemygc.com` service:
43
+
44
+ ``` sh
45
+ Lourenss-MacBook-Air-2:discourse lourens$ bundle exec tunemygc -r lourens@bearmetal.eu
46
+ Application registered. Use RUBY_GC_TOKEN=08de9e8822c847244b31290cedfc1d51 in your environment.
47
+ ```
48
+
49
+ We require a valid email address as a canonical reference for tuner tokens for your applications.
50
+
51
+ For the above command sequences, to sample your Rails app for tuning, run:
52
+
53
+ ``` sh
54
+ RUBY_GC_TOKEN=08de9e8822c847244b31290cedfc1d51 RUBY_GC_TUNE=1 bundle exec rails s
55
+ ```
56
+
57
+ The CLI interface supports retrieving configuration options for your application as well.
58
+
59
+ ``` sh
60
+ Lourenss-MacBook-Air-2:discourse lourens$ bundle exec tunemygc
61
+ Usage: tunemygc [options]
62
+ -r, --register EMAIL Register this Rails app with the https://tunemygc.com service
63
+ -c, --config TOKEN Fetch the last known config for a given Rails app
64
+ -h, --help How to use the TuneMyGC agent CLI
65
+ ```
66
+
67
+ ## Configuration options
68
+
69
+ We fully embrace and encourage [12 factor](http://12factor.net) conventions and as such configuration is limited to a few environment variables. No config files and YAML or initializer cruft.
70
+
71
+ #### Basic
72
+
73
+ * `RUBY_GC_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`
74
+
75
+ This application specific token is required for GC instrumentation. You can generate one from the CLI interface by registering for the service with a valid email address:
76
+
77
+ ``` sh
78
+ Lourenss-MacBook-Air-2:discourse lourens$ bundle exec tunemygc -r lourens@bearmetal.eu
79
+ Application registered. Use RUBY_GC_TOKEN=08de9e8822c847244b31290cedfc1d51 in your environment.
80
+ ```
81
+
82
+ * `RUBY_GC_TUNE=1`
83
+
84
+ Enables the interposer for taking a few lightweight snapshots and submitting them to `tunemygc.com`. Without this environment variable set, it won't interpose itself.
85
+
86
+ For the above command sequences, to sample my Rails app for tuning, I'd run:
87
+
88
+ ``` sh
89
+ RUBY_GC_TOKEN=08de9e8822c847244b31290cedfc1d51 RUBY_GC_TUNE=1 bundle exec rails s
90
+ ```
91
+
92
+ #### Advanced
93
+
94
+ * `RUBY_GC_TUNE_REQUESTS=x`
95
+
96
+ Controls the interposer lifetime for sampling requests. It will enable itself, then remove request instrumentation after `x` requests. A good minimum ballpark sample set would be 200
97
+
98
+ * `RUBY_GC_TUNE_DEBUG=1`
99
+
100
+ As above, but dumps snapshots to Rails logger or STDOUT prior to submission. Mostly for developer use/support.
101
+
102
+ ## How do I use this?
103
+
104
+ This gem is only a lightweight agent and designed to not get in your way. There's not much workflow at the moment other than applying the suggested GC configuration to your application's environment.
105
+
106
+ #### Interpreting configurations
107
+
108
+ An instrumented process dumps a reccommended config to the Rails logger.
109
+
110
+ ``` sh
111
+ [TuneMyGC] Syncing 688 snapshots
112
+ [TuneMyGC] ==== Recommended GC configs from https://tunemygc.com/configs/d739119e4abc38d42e183d1361991818.json
113
+ [TuneMyGC] export RUBY_GC_HEAP_INIT_SLOTS=382429
114
+ [TuneMyGC] export RUBY_GC_HEAP_FREE_SLOTS=603850
115
+ [TuneMyGC] export RUBY_GC_HEAP_GROWTH_FACTOR=1.2
116
+ [TuneMyGC] export RUBY_GC_HEAP_GROWTH_MAX_SLOTS=301925
117
+ [TuneMyGC] export RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR=2.0
118
+ [TuneMyGC] export RUBY_GC_MALLOC_LIMIT=35818030
119
+ [TuneMyGC] export RUBY_GC_MALLOC_LIMIT_MAX=42981636
120
+ [TuneMyGC] export RUBY_GC_MALLOC_LIMIT_GROWTH_FACTOR=1.32
121
+ [TuneMyGC] export RUBY_GC_OLDMALLOC_LIMIT=32782669
122
+ [TuneMyGC] export RUBY_GC_OLDMALLOC_LIMIT_MAX=49174003.5
123
+ [TuneMyGC] export RUBY_GC_OLDMALLOC_LIMIT_GROWTH_FACTOR=1.2
124
+ ```
125
+
126
+ We're still in the process of building tools and a launcher shim around this. You can also retrieve the last known configuration for you app via the CLI interface:
127
+
128
+ ``` sh
129
+ Lourenss-MacBook-Air-2:discourse lourens$ bundle exec tunemygc -c 3b8796e5627f97ec760f000d55d9b3f5
130
+ === Suggested GC configuration:
131
+
132
+ export RUBY_GC_HEAP_INIT_SLOTS=382429
133
+ export RUBY_GC_HEAP_FREE_SLOTS=603850
134
+ export RUBY_GC_HEAP_GROWTH_FACTOR=1.2
135
+ export RUBY_GC_HEAP_GROWTH_MAX_SLOTS=301925
136
+ export RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR=2.0
137
+ export RUBY_GC_MALLOC_LIMIT=35818030
138
+ export RUBY_GC_MALLOC_LIMIT_MAX=42981636
139
+ export RUBY_GC_MALLOC_LIMIT_GROWTH_FACTOR=1.32
140
+ export RUBY_GC_OLDMALLOC_LIMIT=32782669
141
+ export RUBY_GC_OLDMALLOC_LIMIT_MAX=49174003.5
142
+ export RUBY_GC_OLDMALLOC_LIMIT_GROWTH_FACTOR=1.2
143
+ ```
144
+
145
+ #### Heroku and 12 factor
146
+
147
+ We have a [Heroku](http://www.heroku.com) addon in Alpha testing and the Ruby GC lends itself well to tuning through 12 factor principles as it's designed around environment variables.
148
+
149
+ ## Security and privacy concerns
150
+
151
+ We don't track any data specific to your application other than a simple environment header which allows us to pick the best tuner for your setup:
152
+
153
+ * Ruby version eg. "2.2.0"
154
+ * Rails version eg. "4.1.8"
155
+ * Compile time GC options eg. "["USE_RGENGC", "RGENGC_ESTIMATE_OLDMALLOC", "GC_ENABLE_LAZY_SWEEP"]"
156
+ * Compile time GC constants eg. "{"RVALUE_SIZE"=>40, "HEAP_OBJ_LIMIT"=>408, "HEAP_BITMAP_SIZE"=>56, "HEAP_BITMAP_PLANES"=>3}"
157
+
158
+ Samples hitting our tuner endpoint doesn't include any proprietary details from your application either - just data points about GC activity.
159
+
160
+ We do however ask for a valid email address as a canonical reference for tuner tokens for your applications.
161
+
162
+ ## Feedback and issues
163
+
164
+ When trouble strikes, please file an [issue](https://www.github.com/bear-metal/tunemygc/issues) or email Lourens directly <lourens@bearmetal.eu>
165
+
166
+ [Bear Metal OÜ](http://www.bearmetal.eu) is also available for consulting around general Rails performance, heap dump analysis (more tools coming soon) and custom Ruby extension development.
167
+
168
+ ## License
169
+
170
+ (The MIT License)
171
+
172
+ Copyright (c) 2015:
173
+
174
+ * [Bear Metal OÜ](http://bearmetal.eu)
175
+
176
+ Permission is hereby granted, free of charge, to any person obtaining
177
+ a copy of this software and associated documentation files (the
178
+ 'Software'), to deal in the Software without restriction, including
179
+ without limitation the rights to use, copy, modify, merge, publish,
180
+ distribute, sublicense, and/or sell copies of the Software, and to
181
+ permit persons to whom the Software is furnished to do so, subject to
182
+ the following conditions:
183
+
184
+ The above copyright notice and this permission notice shall be
185
+ included in all copies or substantial portions of the Software.
186
+
187
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
188
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
189
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
190
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
191
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
192
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
193
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,32 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems' unless defined?(Gem)
4
+ require 'rake' unless defined?(Rake)
5
+
6
+ require 'rake/extensiontask'
7
+ require 'rake/testtask'
8
+
9
+ Rake::ExtensionTask.new('tunemygc') do |ext|
10
+ ext.name = 'tunemygc_ext'
11
+ ext.ext_dir = 'ext/tunemygc'
12
+ ext.lib_dir = "lib/tunemygc"
13
+ CLEAN.include 'lib/**/tunemygc_ext.*'
14
+ end
15
+
16
+ desc 'Run tunemygc tests'
17
+ Rake::TestTask.new(:test) do |t|
18
+ t.libs << 'test'
19
+ t.pattern = "test/**/test_*.rb"
20
+ t.verbose = true
21
+ t.warning = true
22
+ end
23
+
24
+ namespace :debug do
25
+ desc "Run the test suite under gdb"
26
+ task :gdb do
27
+ system "gdb --args ruby rake"
28
+ end
29
+ end
30
+
31
+ task :test => :compile
32
+ task :default => :test
Binary file
data/bin/tunemygc ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'tunemygc'
4
+ require 'tunemygc/cli'
5
+
6
+ TuneMyGc::CLI.start(ARGV)
@@ -0,0 +1,92 @@
1
+ # encoding: utf-8
2
+
3
+ require 'mkmf'
4
+
5
+ dir_config('tunemygc')
6
+
7
+ # Only defined for Ruby 2.1.x and 2.2.x
8
+ gc_events = have_const('RUBY_INTERNAL_EVENT_GC_END_SWEEP')
9
+
10
+ if gc_events
11
+ # From ko1/gc_tracer
12
+ # Piggy backs off the new methods to retrieve GC stats and latest cycle info without doing
13
+ # allocations - thus safe to call within a GC cycle and properly snapshot what we need without
14
+ # the results being skewed by postponed jobs, which isn't deterministic.
15
+ open("tunemygc_env.h", 'w'){|f|
16
+ gc_stat = GC.stat
17
+ gc_latest_info = GC.latest_gc_info
18
+ f.puts '#include "ruby/ruby.h"'
19
+ f.puts "static VALUE sym_gc_stat[#{gc_stat.keys.size}];"
20
+ f.puts "static VALUE sym_latest_gc_info[#{gc_latest_info.keys.size}];"
21
+
22
+ f.puts 'typedef struct {'
23
+ f.puts ' double ts;'
24
+ f.puts ' size_t peak_rss;'
25
+ f.puts ' size_t current_rss;'
26
+ f.puts ' VALUE stage;'
27
+ gc_stat.keys.each do |key|
28
+ f.puts " size_t #{key};"
29
+ end
30
+ gc_latest_info.each do |key, val|
31
+ f.puts " VALUE #{key};"
32
+ end
33
+ f.puts '} tunemygc_stat_record;'
34
+
35
+ f.puts "static void"
36
+ f.puts "tunemygc_set_stat_record(tunemygc_stat_record *record)"
37
+ f.puts "{"
38
+ #
39
+ gc_stat.keys.each.with_index{|k, i|
40
+ f.puts " record->#{k} = rb_gc_stat(sym_gc_stat[#{i}]);"
41
+ }
42
+ gc_latest_info.keys.each.with_index{|k, i|
43
+ f.puts " record->#{k} = rb_gc_latest_gc_info(sym_latest_gc_info[#{i}]);"
44
+ }
45
+ #
46
+ f.puts "}"
47
+
48
+ f.puts "static VALUE"
49
+ f.puts "tunemygc_get_stat_record(tunemygc_stat_record *record)"
50
+ f.puts "{"
51
+ #
52
+ f.puts " VALUE stat = rb_hash_new();"
53
+ f.puts " VALUE latest_info = rb_hash_new();"
54
+ f.puts " VALUE snapshot = rb_ary_new2(7);"
55
+ gc_stat.keys.each.with_index{|k, i|
56
+ f.puts " rb_hash_aset(stat, sym_gc_stat[#{i}], SIZET2NUM(record->#{k}));"
57
+ }
58
+ gc_latest_info.keys.each.with_index{|k, i|
59
+ f.puts " rb_hash_aset(latest_info, sym_latest_gc_info[#{i}], record->#{k});"
60
+ }
61
+ f.puts " rb_ary_store(snapshot, 0, DBL2NUM(record->ts));"
62
+ f.puts " rb_ary_store(snapshot, 1, SIZET2NUM(record->peak_rss));"
63
+ f.puts " rb_ary_store(snapshot, 2, SIZET2NUM(record->current_rss));"
64
+ f.puts " rb_ary_store(snapshot, 3, record->stage);"
65
+ f.puts " rb_ary_store(snapshot, 4, stat);"
66
+ f.puts " rb_ary_store(snapshot, 5, latest_info);"
67
+ f.puts " rb_ary_store(snapshot, 6, Qnil);"
68
+ f.puts " return snapshot;"
69
+ #
70
+ f.puts "}"
71
+
72
+ f.puts "static void"
73
+ f.puts "tunemygc_setup_trace_symbols(void)"
74
+ f.puts "{"
75
+ #
76
+ gc_stat.keys.each.with_index{|k, i|
77
+ f.puts " sym_gc_stat[#{i}] = ID2SYM(rb_intern(\"#{k}\"));"
78
+ }
79
+ gc_latest_info.keys.each.with_index{|k, i|
80
+ f.puts " sym_latest_gc_info[#{i}] = ID2SYM(rb_intern(\"#{k}\"));"
81
+ }
82
+ #
83
+ f.puts "}"
84
+ }
85
+
86
+ create_makefile('tunemygc/tunemygc_ext')
87
+ else
88
+ # do nothing if we're not running within Ruby 2.1.x or 2.2.x
89
+ File.open('Makefile', 'w') do |f|
90
+ f.puts "install:\n\t\n"
91
+ end
92
+ end
@@ -0,0 +1,122 @@
1
+ /*
2
+ * Author: David Robert Nadeau
3
+ * Site: http://NadeauSoftware.com/
4
+ * License: Creative Commons Attribution 3.0 Unported License
5
+ * http://creativecommons.org/licenses/by/3.0/deed.en_US
6
+ */
7
+
8
+ #if defined(_WIN32)
9
+ #include <windows.h>
10
+ #include <psapi.h>
11
+
12
+ #elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
13
+ #include <unistd.h>
14
+ #include <sys/resource.h>
15
+
16
+ #if defined(__APPLE__) && defined(__MACH__)
17
+ #include <mach/mach.h>
18
+
19
+ #elif (defined(_AIX) || defined(__TOS__AIX__)) || (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__)))
20
+ #include <fcntl.h>
21
+ #include <procfs.h>
22
+
23
+ #elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__)
24
+ #include <stdio.h>
25
+
26
+ #endif
27
+
28
+ #else
29
+ #error "Cannot define getPeakRSS( ) or getCurrentRSS( ) for an unknown OS."
30
+ #endif
31
+
32
+
33
+
34
+
35
+
36
+ /**
37
+ * Returns the peak (maximum so far) resident set size (physical
38
+ * memory use) measured in bytes, or zero if the value cannot be
39
+ * determined on this OS.
40
+ */
41
+ size_t getPeakRSS( )
42
+ {
43
+ #if defined(_WIN32)
44
+ /* Windows -------------------------------------------------- */
45
+ PROCESS_MEMORY_COUNTERS info;
46
+ GetProcessMemoryInfo( GetCurrentProcess( ), &info, sizeof(info) );
47
+ return (size_t)info.PeakWorkingSetSize;
48
+
49
+ #elif (defined(_AIX) || defined(__TOS__AIX__)) || (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__)))
50
+ /* AIX and Solaris ------------------------------------------ */
51
+ struct psinfo psinfo;
52
+ int fd = -1;
53
+ if ( (fd = open( "/proc/self/psinfo", O_RDONLY )) == -1 )
54
+ return (size_t)0L; /* Can't open? */
55
+ if ( read( fd, &psinfo, sizeof(psinfo) ) != sizeof(psinfo) )
56
+ {
57
+ close( fd );
58
+ return (size_t)0L; /* Can't read? */
59
+ }
60
+ close( fd );
61
+ return (size_t)(psinfo.pr_rssize * 1024L);
62
+
63
+ #elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
64
+ /* BSD, Linux, and OSX -------------------------------------- */
65
+ struct rusage rusage;
66
+ getrusage( RUSAGE_SELF, &rusage );
67
+ #if defined(__APPLE__) && defined(__MACH__)
68
+ return (size_t)rusage.ru_maxrss;
69
+ #else
70
+ return (size_t)(rusage.ru_maxrss * 1024L);
71
+ #endif
72
+
73
+ #else
74
+ /* Unknown OS ----------------------------------------------- */
75
+ return (size_t)0L; /* Unsupported. */
76
+ #endif
77
+ }
78
+
79
+
80
+
81
+
82
+
83
+ /**
84
+ * Returns the current resident set size (physical memory use) measured
85
+ * in bytes, or zero if the value cannot be determined on this OS.
86
+ */
87
+ size_t getCurrentRSS( )
88
+ {
89
+ #if defined(_WIN32)
90
+ /* Windows -------------------------------------------------- */
91
+ PROCESS_MEMORY_COUNTERS info;
92
+ GetProcessMemoryInfo( GetCurrentProcess( ), &info, sizeof(info) );
93
+ return (size_t)info.WorkingSetSize;
94
+
95
+ #elif defined(__APPLE__) && defined(__MACH__)
96
+ /* OSX ------------------------------------------------------ */
97
+ struct mach_task_basic_info info;
98
+ mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT;
99
+ if ( task_info( mach_task_self( ), MACH_TASK_BASIC_INFO,
100
+ (task_info_t)&info, &infoCount ) != KERN_SUCCESS )
101
+ return (size_t)0L; /* Can't access? */
102
+ return (size_t)info.resident_size;
103
+
104
+ #elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__)
105
+ /* Linux ---------------------------------------------------- */
106
+ long rss = 0L;
107
+ FILE* fp = NULL;
108
+ if ( (fp = fopen( "/proc/self/statm", "r" )) == NULL )
109
+ return (size_t)0L; /* Can't open? */
110
+ if ( fscanf( fp, "%*s%ld", &rss ) != 1 )
111
+ {
112
+ fclose( fp );
113
+ return (size_t)0L; /* Can't read? */
114
+ }
115
+ fclose( fp );
116
+ return (size_t)rss * (size_t)sysconf( _SC_PAGESIZE);
117
+
118
+ #else
119
+ /* AIX, BSD, Solaris, and Unknown OS ------------------------ */
120
+ return (size_t)0L; /* Unsupported. */
121
+ #endif
122
+ }