rails-perftest 0.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.
Files changed (33) hide show
  1. data/.gitignore +17 -0
  2. data/Gemfile +6 -0
  3. data/LICENSE +22 -0
  4. data/README.md +696 -0
  5. data/Rakefile +37 -0
  6. data/bin/perftest +9 -0
  7. data/lib/generators/rails/app/templates/test/performance/browsing_test.rb +12 -0
  8. data/lib/generators/rails/performance_test/USAGE +10 -0
  9. data/lib/generators/rails/performance_test/performance_test_generator.rb +14 -0
  10. data/lib/generators/rails/performance_test/templates/performance_test.rb +12 -0
  11. data/lib/rails-perftest.rb +2 -0
  12. data/lib/rails/performance_test_help.rb +3 -0
  13. data/lib/rails/perftest/action_controller.rb +3 -0
  14. data/lib/rails/perftest/action_controller/performance_test.rb +3 -0
  15. data/lib/rails/perftest/action_dispatch.rb +3 -0
  16. data/lib/rails/perftest/action_dispatch/performance_test.rb +10 -0
  17. data/lib/rails/perftest/active_support/testing/performance.rb +271 -0
  18. data/lib/rails/perftest/active_support/testing/performance/jruby.rb +115 -0
  19. data/lib/rails/perftest/active_support/testing/performance/rubinius.rb +113 -0
  20. data/lib/rails/perftest/active_support/testing/performance/ruby.rb +173 -0
  21. data/lib/rails/perftest/commands.rb +30 -0
  22. data/lib/rails/perftest/commands/benchmarker.rb +34 -0
  23. data/lib/rails/perftest/commands/profiler.rb +32 -0
  24. data/lib/rails/perftest/railtie.rb +20 -0
  25. data/lib/rails/perftest/railties/testing.tasks +12 -0
  26. data/lib/rails/perftest/version.rb +5 -0
  27. data/rails-perftest.gemspec +26 -0
  28. data/rails-perftest.gemspec.erb +26 -0
  29. data/test/generators/generators_test_helper.rb +16 -0
  30. data/test/generators/performance_test_generator_test.rb +18 -0
  31. data/test/helper.rb +8 -0
  32. data/test/performance_test.rb +58 -0
  33. metadata +171 -0
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ .rvmrc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rails-perftest.gemspec
4
+ gemspec
5
+
6
+ gem 'rails', github: 'rails/rails', branch: 'master'
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Yves Senn
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,696 @@
1
+ Performance Testing Rails Applications
2
+ ======================================
3
+
4
+ This guide covers the various ways of performance testing a Ruby on Rails
5
+ application.
6
+
7
+ After reading this guide, you will know:
8
+
9
+ * The various types of benchmarking and profiling metrics.
10
+ * How to generate performance and benchmarking tests.
11
+ * How to install and use a GC-patched Ruby binary to measure memory usage and object
12
+ allocation.
13
+ * The benchmarking information provided by Rails inside the log files.
14
+ * Various tools facilitating benchmarking and profiling.
15
+
16
+ Performance testing is an integral part of the development cycle. It is very
17
+ important that you don't make your end users wait for too long before the page
18
+ is completely loaded. Ensuring a pleasant browsing experience for end users and
19
+ cutting the cost of unnecessary hardware is important for any non-trivial web
20
+ application.
21
+
22
+ --------------------------------------------------------------------------------
23
+
24
+ Installation
25
+ ----------------------
26
+
27
+ As of rails 4 performance tests are no longer part of the default
28
+ stack. If you want to use performance tests simply follow these instructions.
29
+
30
+ Add this line to your application's Gemfile:
31
+
32
+ gem 'rails-perftest'
33
+
34
+ Performance Test Cases
35
+ ----------------------
36
+
37
+ Rails performance tests are a special type of integration tests, designed for
38
+ benchmarking and profiling the test code. With performance tests, you can
39
+ determine where your application's memory or speed problems are coming from,
40
+ and get a more in-depth picture of those problems.
41
+
42
+ In a freshly generated Rails application, `test/performance/browsing_test.rb`
43
+ contains an example of a performance test:
44
+
45
+ ```ruby
46
+ require 'test_helper'
47
+ require 'rails/performance_test_help'
48
+
49
+ class BrowsingTest < ActionDispatch::PerformanceTest
50
+ # Refer to the documentation for all available options
51
+ # self.profile_options = { runs: 5, metrics: [:wall_time, :memory],
52
+ # output: 'tmp/performance', formats: [:flat] }
53
+
54
+ test "homepage" do
55
+ get '/'
56
+ end
57
+ end
58
+ ```
59
+
60
+ This example is a simple performance test case for profiling a GET request to
61
+ the application's homepage.
62
+
63
+ ### Generating Performance Tests
64
+
65
+ Rails provides a generator called `performance_test` for creating new
66
+ performance tests:
67
+
68
+ ```bash
69
+ $ rails generate performance_test homepage
70
+ ```
71
+
72
+ This generates `homepage_test.rb` in the `test/performance` directory:
73
+
74
+ ```ruby
75
+ require 'test_helper'
76
+ require 'rails/performance_test_help'
77
+
78
+ class HomepageTest < ActionDispatch::PerformanceTest
79
+ # Refer to the documentation for all available options
80
+ # self.profile_options = { runs: 5, metrics: [:wall_time, :memory],
81
+ # output: 'tmp/performance', formats: [:flat] }
82
+
83
+ test "homepage" do
84
+ get '/'
85
+ end
86
+ end
87
+ ```
88
+
89
+ ### Examples
90
+
91
+ Let's assume your application has the following controller and model:
92
+
93
+ ```ruby
94
+ # routes.rb
95
+ root to: 'home#dashboard'
96
+ resources :posts
97
+
98
+ # home_controller.rb
99
+ class HomeController < ApplicationController
100
+ def dashboard
101
+ @users = User.last_ten.includes(:avatars)
102
+ @posts = Post.all_today
103
+ end
104
+ end
105
+
106
+ # posts_controller.rb
107
+ class PostsController < ApplicationController
108
+ def create
109
+ @post = Post.create(params[:post])
110
+ redirect_to(@post)
111
+ end
112
+ end
113
+
114
+ # post.rb
115
+ class Post < ActiveRecord::Base
116
+ before_save :recalculate_costly_stats
117
+
118
+ def slow_method
119
+ # I fire gallzilion queries sleeping all around
120
+ end
121
+
122
+ private
123
+
124
+ def recalculate_costly_stats
125
+ # CPU heavy calculations
126
+ end
127
+ end
128
+ ```
129
+
130
+ #### Controller Example
131
+
132
+ Because performance tests are a special kind of integration test, you can use
133
+ the `get` and `post` methods in them.
134
+
135
+ Here's the performance test for `HomeController#dashboard` and
136
+ `PostsController#create`:
137
+
138
+ ```ruby
139
+ require 'test_helper'
140
+ require 'rails/performance_test_help'
141
+
142
+ class PostPerformanceTest < ActionDispatch::PerformanceTest
143
+ def setup
144
+ # Application requires logged-in user
145
+ login_as(:lifo)
146
+ end
147
+
148
+ test "homepage" do
149
+ get '/dashboard'
150
+ end
151
+
152
+ test "creating new post" do
153
+ post '/posts', post: { body: 'lifo is fooling you' }
154
+ end
155
+ end
156
+ ```
157
+
158
+ You can find more details about the `get` and `post` methods in the
159
+ [Testing Rails Applications](testing.html) guide.
160
+
161
+ #### Model Example
162
+
163
+ Even though the performance tests are integration tests and hence closer to
164
+ the request/response cycle by nature, you can still performance test pure model
165
+ code.
166
+
167
+ Performance test for `Post` model:
168
+
169
+ ```ruby
170
+ require 'test_helper'
171
+ require 'rails/performance_test_help'
172
+
173
+ class PostModelTest < ActionDispatch::PerformanceTest
174
+ test "creation" do
175
+ Post.create body: 'still fooling you', cost: '100'
176
+ end
177
+
178
+ test "slow method" do
179
+ # Using posts(:awesome) fixture
180
+ posts(:awesome).slow_method
181
+ end
182
+ end
183
+ ```
184
+
185
+ ### Modes
186
+
187
+ Performance tests can be run in two modes: Benchmarking and Profiling.
188
+
189
+ #### Benchmarking
190
+
191
+ Benchmarking makes it easy to quickly gather a few metrics about each test run.
192
+ By default, each test case is run **4 times** in benchmarking mode.
193
+
194
+ To run performance tests in benchmarking mode:
195
+
196
+ ```bash
197
+ $ rake test:benchmark
198
+ ```
199
+
200
+ #### Profiling
201
+
202
+ Profiling allows you to make an in-depth analysis of each of your tests by using
203
+ an external profiler. Depending on your Ruby interpreter, this profiler can be
204
+ native (Rubinius, JRuby) or not (MRI, which uses RubyProf). By default, each
205
+ test case is run **once** in profiling mode.
206
+
207
+ To run performance tests in profiling mode:
208
+
209
+ ```bash
210
+ $ rake test:profile
211
+ ```
212
+
213
+ ### Metrics
214
+
215
+ Benchmarking and profiling run performance tests and give you multiple metrics.
216
+ The availability of each metric is determined by the interpreter being used—none
217
+ of them support all metrics—and by the mode in use. A brief description of each
218
+ metric and their availability across interpreters/modes is given below.
219
+
220
+ #### Wall Time
221
+
222
+ Wall time measures the real world time elapsed during the test run. It is
223
+ affected by any other processes concurrently running on the system.
224
+
225
+ #### Process Time
226
+
227
+ Process time measures the time taken by the process. It is unaffected by any
228
+ other processes running concurrently on the same system. Hence, process time
229
+ is likely to be constant for any given performance test, irrespective of the
230
+ machine load.
231
+
232
+ #### CPU Time
233
+
234
+ Similar to process time, but leverages the more accurate CPU clock counter
235
+ available on the Pentium and PowerPC platforms.
236
+
237
+ #### User Time
238
+
239
+ User time measures the amount of time the CPU spent in user-mode, i.e. within
240
+ the process. This is not affected by other processes and by the time it possibly
241
+ spends blocked.
242
+
243
+ #### Memory
244
+
245
+ Memory measures the amount of memory used for the performance test case.
246
+
247
+ #### Objects
248
+
249
+ Objects measures the number of objects allocated for the performance test case.
250
+
251
+ #### GC Runs
252
+
253
+ GC Runs measures the number of times GC was invoked for the performance test case.
254
+
255
+ #### GC Time
256
+
257
+ GC Time measures the amount of time spent in GC for the performance test case.
258
+
259
+ #### Metric Availability
260
+
261
+ ##### Benchmarking
262
+
263
+ | Interpreter | Wall Time | Process Time | CPU Time | User Time | Memory | Objects | GC Runs | GC Time |
264
+ | ------------ | --------- | ------------ | -------- | --------- | ------ | ------- | ------- | ------- |
265
+ | **MRI** | yes | yes | yes | no | yes | yes | yes | yes |
266
+ | **REE** | yes | yes | yes | no | yes | yes | yes | yes |
267
+ | **Rubinius** | yes | no | no | no | yes | yes | yes | yes |
268
+ | **JRuby** | yes | no | no | yes | yes | yes | yes | yes |
269
+
270
+ ##### Profiling
271
+
272
+ | Interpreter | Wall Time | Process Time | CPU Time | User Time | Memory | Objects | GC Runs | GC Time |
273
+ | ------------ | --------- | ------------ | -------- | --------- | ------ | ------- | ------- | ------- |
274
+ | **MRI** | yes | yes | no | no | yes | yes | yes | yes |
275
+ | **REE** | yes | yes | no | no | yes | yes | yes | yes |
276
+ | **Rubinius** | yes | no | no | no | no | no | no | no |
277
+ | **JRuby** | yes | no | no | no | no | no | no | no |
278
+
279
+ NOTE: To profile under JRuby you'll need to run `export JRUBY_OPTS="-Xlaunch.inproc=false --profile.api"`
280
+ **before** the performance tests.
281
+
282
+ ### Understanding the Output
283
+
284
+ Performance tests generate different outputs inside `tmp/performance` directory
285
+ depending on their mode and metric.
286
+
287
+ #### Benchmarking
288
+
289
+ In benchmarking mode, performance tests generate two types of outputs.
290
+
291
+ ##### Command Line
292
+
293
+ This is the primary form of output in benchmarking mode. Example:
294
+
295
+ ```bash
296
+ BrowsingTest#test_homepage (31 ms warmup)
297
+ wall_time: 6 ms
298
+ memory: 437.27 KB
299
+ objects: 5,514
300
+ gc_runs: 0
301
+ gc_time: 19 ms
302
+ ```
303
+
304
+ ##### CSV Files
305
+
306
+ Performance test results are also appended to `.csv` files inside `tmp/performance`.
307
+ For example, running the default `BrowsingTest#test_homepage` will generate
308
+ following five files:
309
+
310
+ * BrowsingTest#test_homepage_gc_runs.csv
311
+ * BrowsingTest#test_homepage_gc_time.csv
312
+ * BrowsingTest#test_homepage_memory.csv
313
+ * BrowsingTest#test_homepage_objects.csv
314
+ * BrowsingTest#test_homepage_wall_time.csv
315
+
316
+ As the results are appended to these files each time the performance tests are
317
+ run in benchmarking mode, you can collect data over a period of time. This can
318
+ be very helpful in analyzing the effects of code changes.
319
+
320
+ Sample output of `BrowsingTest#test_homepage_wall_time.csv`:
321
+
322
+ ```bash
323
+ measurement,created_at,app,rails,ruby,platform
324
+ 0.00738224999999992,2009-01-08T03:40:29Z,,3.0.0,ruby-1.8.7.249,x86_64-linux
325
+ 0.00755874999999984,2009-01-08T03:46:18Z,,3.0.0,ruby-1.8.7.249,x86_64-linux
326
+ 0.00762099999999993,2009-01-08T03:49:25Z,,3.0.0,ruby-1.8.7.249,x86_64-linux
327
+ 0.00603075000000008,2009-01-08T04:03:29Z,,3.0.0,ruby-1.8.7.249,x86_64-linux
328
+ 0.00619899999999995,2009-01-08T04:03:53Z,,3.0.0,ruby-1.8.7.249,x86_64-linux
329
+ 0.00755449999999991,2009-01-08T04:04:55Z,,3.0.0,ruby-1.8.7.249,x86_64-linux
330
+ 0.00595999999999997,2009-01-08T04:05:06Z,,3.0.0,ruby-1.8.7.249,x86_64-linux
331
+ 0.00740450000000004,2009-01-09T03:54:47Z,,3.0.0,ruby-1.8.7.249,x86_64-linux
332
+ 0.00603150000000008,2009-01-09T03:54:57Z,,3.0.0,ruby-1.8.7.249,x86_64-linux
333
+ 0.00771250000000012,2009-01-09T15:46:03Z,,3.0.0,ruby-1.8.7.249,x86_64-linux
334
+ ```
335
+
336
+ #### Profiling
337
+
338
+ In profiling mode, performance tests can generate multiple types of outputs.
339
+ The command line output is always presented but support for the others is
340
+ dependent on the interpreter in use. A brief description of each type and
341
+ their availability across interpreters is given below.
342
+
343
+ ##### Command Line
344
+
345
+ This is a very basic form of output in profiling mode:
346
+
347
+ ```bash
348
+ BrowsingTest#test_homepage (58 ms warmup)
349
+ process_time: 63 ms
350
+ memory: 832.13 KB
351
+ objects: 7,882
352
+ ```
353
+
354
+ ##### Flat
355
+
356
+ Flat output shows the metric—time, memory, etc—measure in each method.
357
+ [Check Ruby-Prof documentation for a better explanation](http://ruby-prof.rubyforge.org/files/examples/flat_txt.html).
358
+
359
+ ##### Graph
360
+
361
+ Graph output shows the metric measure in each method, which methods call it and
362
+ which methods it calls. [Check Ruby-Prof documentation for a better explanation](http://ruby-prof.rubyforge.org/files/examples/graph_txt.html).
363
+
364
+ ##### Tree
365
+
366
+ Tree output is profiling information in calltree format for use by [kcachegrind](http://kcachegrind.sourceforge.net/html/Home.html)
367
+ and similar tools.
368
+
369
+ ##### Output Availability
370
+
371
+ | | Flat | Graph | Tree |
372
+ | ------------ | ---- | ----- | ---- |
373
+ | **MRI** | yes | yes | yes |
374
+ | **REE** | yes | yes | yes |
375
+ | **Rubinius** | yes | yes | no |
376
+ | **JRuby** | yes | yes | no |
377
+
378
+ ### Tuning Test Runs
379
+
380
+ Test runs can be tuned by setting the `profile_options` class variable on your
381
+ test class.
382
+
383
+ ```ruby
384
+ require 'test_helper'
385
+ require 'rails/performance_test_help'
386
+
387
+ class BrowsingTest < ActionDispatch::PerformanceTest
388
+ self.profile_options = { runs: 5, metrics: [:wall_time, :memory] }
389
+
390
+ test "homepage"
391
+ get '/'
392
+ end
393
+ end
394
+ ```
395
+
396
+ In this example, the test would run 5 times and measure wall time and memory.
397
+ There are a few configurable options:
398
+
399
+ | Option | Description | Default | Mode |
400
+ | ---------- | ------------------------------------------ | ----------------------------- | --------- |
401
+ | `:runs` | Number of runs. | Benchmarking: 4, Profiling: 1 | Both |
402
+ | `:output` | Directory to use when writing the results. | `tmp/performance` | Both |
403
+ | `:metrics` | Metrics to use. | See below. | Both |
404
+ | `:formats` | Formats to output to. | See below. | Profiling |
405
+
406
+ Metrics and formats have different defaults depending on the interpreter in use.
407
+
408
+ | Interpreter | Mode | Default metrics | Default formats |
409
+ | -------------- | ------------ | ------------------------------------------------------- | ----------------------------------------------- |
410
+ | **MRI/REE** | Benchmarking | `[:wall_time, :memory, :objects, :gc_runs, :gc_time]` | N/A |
411
+ | | Profiling | `[:process_time, :memory, :objects]` | `[:flat, :graph_html, :call_tree, :call_stack]` |
412
+ | **Rubinius** | Benchmarking | `[:wall_time, :memory, :objects, :gc_runs, :gc_time]` | N/A |
413
+ | | Profiling | `[:wall_time]` | `[:flat, :graph]` |
414
+ | **JRuby** | Benchmarking | `[:wall_time, :user_time, :memory, :gc_runs, :gc_time]` | N/A |
415
+ | | Profiling | `[:wall_time]` | `[:flat, :graph]` |
416
+
417
+ As you've probably noticed by now, metrics and formats are specified using a
418
+ symbol array with each name [underscored.](http://api.rubyonrails.org/classes/String.html#method-i-underscore)
419
+
420
+ ### Performance Test Environment
421
+
422
+ Performance tests are run in the `test` environment. But running performance
423
+ tests will set the following configuration parameters:
424
+
425
+ ```bash
426
+ ActionController::Base.perform_caching = true
427
+ ActiveSupport::Dependencies.mechanism = :require
428
+ Rails.logger.level = ActiveSupport::Logger::INFO
429
+ ```
430
+
431
+ As `ActionController::Base.perform_caching` is set to `true`, performance tests
432
+ will behave much as they do in the `production` environment.
433
+
434
+ ### Installing GC-Patched MRI
435
+
436
+ To get the best from Rails' performance tests under MRI, you'll need to build
437
+ a special Ruby binary with some super powers.
438
+
439
+ The recommended patches for each MRI version are:
440
+
441
+ | Version | Patch |
442
+ | --------------- | --------- |
443
+ | 1.8.6 | ruby186gc |
444
+ | 1.8.7 | ruby187gc |
445
+ | 1.9.2 and above | gcdata |
446
+
447
+ All of these can be found on [RVM's _patches_ directory](https://github.com/wayneeseguin/rvm/tree/master/patches/ruby)
448
+ under each specific interpreter version.
449
+
450
+ Concerning the installation itself, you can either do this easily by using
451
+ [RVM](https://rvm.io/) or you can build everything from source,
452
+ which is a little bit harder.
453
+
454
+ #### Install Using RVM
455
+
456
+ The process of installing a patched Ruby interpreter is very easy if you let RVM
457
+ do the hard work. All of the following RVM commands will provide you with a
458
+ patched Ruby interpreter:
459
+
460
+ ```bash
461
+ $ rvm install 1.9.2-p180 --patch gcdata
462
+ $ rvm install 1.8.7 --patch ruby187gc
463
+ $ rvm install 1.9.2-p180 --patch ~/Downloads/downloaded_gcdata_patch.patch
464
+ ```
465
+
466
+ You can even keep your regular interpreter by assigning a name to the patched
467
+ one:
468
+
469
+ ```bash
470
+ $ rvm install 1.9.2-p180 --patch gcdata --name gcdata
471
+ $ rvm use 1.9.2-p180 # your regular ruby
472
+ $ rvm use 1.9.2-p180-gcdata # your patched ruby
473
+ ```
474
+
475
+ And it's done! You have installed a patched Ruby interpreter.
476
+
477
+ #### Install From Source
478
+
479
+ This process is a bit more complicated, but straightforward nonetheless. If
480
+ you've never compiled a Ruby binary before, follow these steps to build a
481
+ Ruby binary inside your home directory.
482
+
483
+ ##### Download and Extract
484
+
485
+ ```bash
486
+ $ mkdir rubygc
487
+ $ wget <the version you want from ftp://ftp.ruby-lang.org/pub/ruby>
488
+ $ tar -xzvf <ruby-version.tar.gz>
489
+ $ cd <ruby-version>
490
+ ```
491
+
492
+ ##### Apply the Patch
493
+
494
+ ```bash
495
+ $ curl http://github.com/wayneeseguin/rvm/raw/master/patches/ruby/1.9.2/p180/gcdata.patch | patch -p0 # if you're on 1.9.2!
496
+ $ curl http://github.com/wayneeseguin/rvm/raw/master/patches/ruby/1.8.7/ruby187gc.patch | patch -p0 # if you're on 1.8.7!
497
+ ```
498
+
499
+ ##### Configure and Install
500
+
501
+ The following will install Ruby in your home directory's `/rubygc` directory.
502
+ Make sure to replace `<homedir>` with a full patch to your actual home
503
+ directory.
504
+
505
+ ```bash
506
+ $ ./configure --prefix=/<homedir>/rubygc
507
+ $ make && make install
508
+ ```
509
+
510
+ ##### Prepare Aliases
511
+
512
+ For convenience, add the following lines in your `~/.profile`:
513
+
514
+ ```bash
515
+ alias gcruby='~/rubygc/bin/ruby'
516
+ alias gcrake='~/rubygc/bin/rake'
517
+ alias gcgem='~/rubygc/bin/gem'
518
+ alias gcirb='~/rubygc/bin/irb'
519
+ alias gcrails='~/rubygc/bin/rails'
520
+ ```
521
+
522
+ Don't forget to use your aliases from now on.
523
+
524
+ ### Using Ruby-Prof on MRI and REE
525
+
526
+ Add Ruby-Prof to your applications' Gemfile if you want to benchmark/profile
527
+ under MRI or REE:
528
+
529
+ ```ruby
530
+ gem 'ruby-prof'
531
+ ```
532
+
533
+ Now run `bundle install` and you're ready to go.
534
+
535
+ Command Line Tools
536
+ ------------------
537
+
538
+ Writing performance test cases could be an overkill when you are looking for one
539
+ time tests. Rails ships with two command line tools that enable quick and dirty
540
+ performance testing:
541
+
542
+ ### `benchmarker`
543
+
544
+ Usage:
545
+
546
+ ```bash
547
+ Usage: rperf benchmarker 'Ruby.code' 'Ruby.more_code' ... [OPTS]
548
+ -r, --runs N Number of runs.
549
+ Default: 4
550
+ -o, --output PATH Directory to use when writing the results.
551
+ Default: tmp/performance
552
+ -m, --metrics a,b,c Metrics to use.
553
+ Default: wall_time,memory,objects,gc_runs,gc_time
554
+ ```
555
+
556
+ Example:
557
+
558
+ ```bash
559
+ $ rperf benchmarker 'Item.all' 'CouchItem.all' --runs 3 --metrics wall_time,memory
560
+ ```
561
+
562
+ ### `profiler`
563
+
564
+ Usage:
565
+
566
+ ```bash
567
+ Usage: rperf profiler 'Ruby.code' 'Ruby.more_code' ... [OPTS]
568
+ -r, --runs N Number of runs.
569
+ Default: 1
570
+ -o, --output PATH Directory to use when writing the results.
571
+ Default: tmp/performance
572
+ -m, --metrics a,b,c Metrics to use.
573
+ Default: process_time,memory,objects
574
+ -f, --formats x,y,z Formats to output to.
575
+ Default: flat,graph_html,call_tree
576
+ ```
577
+
578
+ Example:
579
+
580
+ ```bash
581
+ $ rperf profiler 'Item.all' 'CouchItem.all' --runs 2 --metrics process_time --formats flat
582
+ ```
583
+
584
+ NOTE: Metrics and formats vary from interpreter to interpreter. Pass `--help` to
585
+ each tool to see the defaults for your interpreter.
586
+
587
+ Helper Methods
588
+ --------------
589
+
590
+ Rails provides various helper methods inside Active Record, Action Controller
591
+ and Action View to measure the time taken by a given piece of code. The method
592
+ is called `benchmark()` in all the three components.
593
+
594
+ ### Model
595
+
596
+ ```ruby
597
+ Project.benchmark("Creating project") do
598
+ project = Project.create("name" => "stuff")
599
+ project.create_manager("name" => "David")
600
+ project.milestones << Milestone.all
601
+ end
602
+ ```
603
+
604
+ This benchmarks the code enclosed in the `Project.benchmark("Creating project") do...end`
605
+ block and prints the result to the log file:
606
+
607
+ ```ruby
608
+ Creating project (185.3ms)
609
+ ```
610
+
611
+ Please refer to the [API docs](http://api.rubyonrails.org/classes/ActiveSupport/Benchmarkable.html#method-i-benchmark)
612
+ for additional options to `benchmark()`.
613
+
614
+ ### Controller
615
+
616
+ Similarly, you could use this helper method inside [controllers.](http://api.rubyonrails.org/classes/ActiveSupport/Benchmarkable.html)
617
+
618
+ ```ruby
619
+ def process_projects
620
+ benchmark("Processing projects") do
621
+ Project.process(params[:project_ids])
622
+ Project.update_cached_projects
623
+ end
624
+ end
625
+ ```
626
+
627
+ NOTE: `benchmark` is a class method inside controllers.
628
+
629
+ ### View
630
+
631
+ And in [views](http://api.rubyonrails.org/classes/ActiveSupport/Benchmarkable.html:)
632
+
633
+ ```erb
634
+ <% benchmark("Showing projects partial") do %>
635
+ <%= render @projects %>
636
+ <% end %>
637
+ ```
638
+
639
+ Request Logging
640
+ ---------------
641
+
642
+ Rails log files contain very useful information about the time taken to serve
643
+ each request. Here's a typical log file entry:
644
+
645
+ ```bash
646
+ Processing ItemsController#index (for 127.0.0.1 at 2009-01-08 03:06:39) [GET]
647
+ Rendering template within layouts/items
648
+ Rendering items/index
649
+ Completed in 5ms (View: 2, DB: 0) | 200 OK [http://0.0.0.0/items]
650
+ ```
651
+
652
+ For this section, we're only interested in the last line:
653
+
654
+ ```bash
655
+ Completed in 5ms (View: 2, DB: 0) | 200 OK [http://0.0.0.0/items]
656
+ ```
657
+
658
+ This data is fairly straightforward to understand. Rails uses millisecond(ms) as
659
+ the metric to measure the time taken. The complete request spent 5 ms inside
660
+ Rails, out of which 2 ms were spent rendering views and none was spent
661
+ communication with the database. It's safe to assume that the remaining 3 ms
662
+ were spent inside the controller.
663
+
664
+ Michael Koziarski has an [interesting blog post](http://www.therailsway.com/2009/1/6/requests-per-second)
665
+ explaining the importance of using milliseconds as the metric.
666
+
667
+ Useful Links
668
+ ------------
669
+
670
+ ### Rails Plugins and Gems
671
+
672
+ * [Rails Analyzer](http://rails-analyzer.rubyforge.org)
673
+ * [Rails Footnotes](https://github.com/josevalim/rails-footnotes/tree/master)
674
+ * [Query Reviewer](https://github.com/nesquena/query_reviewer)
675
+ * [MiniProfiler](http://www.miniprofiler.com)
676
+
677
+ ### Generic Tools
678
+
679
+ * [httperf](http://www.hpl.hp.com/research/linux/httperf/)
680
+ * [ab](http://httpd.apache.org/docs/2.2/programs/ab.html)
681
+ * [JMeter](http://jakarta.apache.org/jmeter/)
682
+ * [kcachegrind](http://kcachegrind.sourceforge.net/html/Home.html)
683
+
684
+ ### Tutorials and Documentation
685
+
686
+ * [ruby-prof API Documentation](http://ruby-prof.rubyforge.org)
687
+ * [Request Profiling Railscast](http://railscasts.com/episodes/98-request-profiling) - Outdated, but useful for understanding call graphs.
688
+
689
+ Commercial Products
690
+ -------------------
691
+
692
+ Rails has been lucky to have a few companies dedicated to Rails-specific
693
+ performance tools. A couple of those are:
694
+
695
+ * [New Relic](http://www.newrelic.com)
696
+ * [Scout](http://scoutapp.com)