rails-perftest 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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)