gitlab-derailed_benchmarks 1.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/check_changelog.yml +10 -0
  3. data/.gitignore +8 -0
  4. data/.gitlab-ci.yml +56 -0
  5. data/.travis.yml +18 -0
  6. data/Appraisals +26 -0
  7. data/CHANGELOG.md +105 -0
  8. data/Gemfile +9 -0
  9. data/README.md +692 -0
  10. data/Rakefile +29 -0
  11. data/bin/derailed +93 -0
  12. data/derailed_benchmarks.gemspec +39 -0
  13. data/gemfiles/.bundle/config +2 -0
  14. data/gemfiles/rails_5_1.gemfile +15 -0
  15. data/gemfiles/rails_5_2.gemfile +15 -0
  16. data/gemfiles/rails_6_0.gemfile +15 -0
  17. data/gemfiles/rails_git.gemfile +19 -0
  18. data/lib/derailed_benchmarks.rb +51 -0
  19. data/lib/derailed_benchmarks/auth_helper.rb +34 -0
  20. data/lib/derailed_benchmarks/auth_helpers/devise.rb +41 -0
  21. data/lib/derailed_benchmarks/core_ext/kernel_require.rb +88 -0
  22. data/lib/derailed_benchmarks/load_tasks.rb +145 -0
  23. data/lib/derailed_benchmarks/require_tree.rb +65 -0
  24. data/lib/derailed_benchmarks/stats_from_dir.rb +128 -0
  25. data/lib/derailed_benchmarks/stats_in_file.rb +60 -0
  26. data/lib/derailed_benchmarks/tasks.rb +292 -0
  27. data/lib/derailed_benchmarks/version.rb +5 -0
  28. data/test/derailed_benchmarks/core_ext/kernel_require_test.rb +33 -0
  29. data/test/derailed_benchmarks/require_tree_test.rb +95 -0
  30. data/test/derailed_benchmarks/stats_from_dir_test.rb +125 -0
  31. data/test/derailed_test.rb +14 -0
  32. data/test/fixtures/require/child_one.rb +4 -0
  33. data/test/fixtures/require/child_two.rb +9 -0
  34. data/test/fixtures/require/parent_one.rb +8 -0
  35. data/test/fixtures/require/raise_child.rb +6 -0
  36. data/test/fixtures/require/relative_child.rb +4 -0
  37. data/test/fixtures/require/relative_child_two.rb +4 -0
  38. data/test/fixtures/stats/significant/loser.bench.txt +100 -0
  39. data/test/fixtures/stats/significant/winner.bench.txt +100 -0
  40. data/test/integration/tasks_test.rb +132 -0
  41. data/test/rails_app/Rakefile +9 -0
  42. data/test/rails_app/app/assets/config/manifest.js +0 -0
  43. data/test/rails_app/app/assets/javascripts/authenticated.js +2 -0
  44. data/test/rails_app/app/assets/stylesheets/authenticated.css +4 -0
  45. data/test/rails_app/app/controllers/application_controller.rb +17 -0
  46. data/test/rails_app/app/controllers/authenticated_controller.rb +8 -0
  47. data/test/rails_app/app/controllers/pages_controller.rb +14 -0
  48. data/test/rails_app/app/helpers/application_helper.rb +4 -0
  49. data/test/rails_app/app/helpers/authenticated_helper.rb +4 -0
  50. data/test/rails_app/app/models/user.rb +13 -0
  51. data/test/rails_app/app/views/authenticated/index.html.erb +1 -0
  52. data/test/rails_app/app/views/layouts/application.html.erb +14 -0
  53. data/test/rails_app/app/views/pages/index.html.erb +1 -0
  54. data/test/rails_app/config.ru +6 -0
  55. data/test/rails_app/config/application.rb +52 -0
  56. data/test/rails_app/config/boot.rb +12 -0
  57. data/test/rails_app/config/database.yml +22 -0
  58. data/test/rails_app/config/environment.rb +11 -0
  59. data/test/rails_app/config/environments/development.rb +27 -0
  60. data/test/rails_app/config/environments/production.rb +51 -0
  61. data/test/rails_app/config/environments/test.rb +37 -0
  62. data/test/rails_app/config/initializers/backtrace_silencers.rb +9 -0
  63. data/test/rails_app/config/initializers/devise.rb +258 -0
  64. data/test/rails_app/config/initializers/inflections.rb +12 -0
  65. data/test/rails_app/config/initializers/mime_types.rb +7 -0
  66. data/test/rails_app/config/initializers/secret_token.rb +13 -0
  67. data/test/rails_app/config/initializers/session_store.rb +10 -0
  68. data/test/rails_app/config/locales/devise.en.yml +59 -0
  69. data/test/rails_app/config/locales/en.yml +9 -0
  70. data/test/rails_app/config/locales/es.yml +10 -0
  71. data/test/rails_app/config/routes.rb +67 -0
  72. data/test/rails_app/db/migrate/20141210070547_devise_create_users.rb +45 -0
  73. data/test/rails_app/db/schema.rb +35 -0
  74. data/test/rails_app/perf.rake +10 -0
  75. data/test/rails_app/public/404.html +26 -0
  76. data/test/rails_app/public/422.html +26 -0
  77. data/test/rails_app/public/500.html +26 -0
  78. data/test/rails_app/public/favicon.ico +0 -0
  79. data/test/rails_app/public/javascripts/application.js +2 -0
  80. data/test/rails_app/public/javascripts/controls.js +965 -0
  81. data/test/rails_app/public/javascripts/dragdrop.js +974 -0
  82. data/test/rails_app/public/javascripts/effects.js +1123 -0
  83. data/test/rails_app/public/javascripts/prototype.js +6001 -0
  84. data/test/rails_app/public/javascripts/rails.js +202 -0
  85. data/test/rails_app/public/stylesheets/.gitkeep +0 -0
  86. data/test/rails_app/script/rails +8 -0
  87. data/test/support/integration_case.rb +7 -0
  88. data/test/test_helper.rb +65 -0
  89. metadata +398 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 15cb069118ce4f9fcfa7a5f4dfb3cc82fce1271b8c0c00fd68c83bd1f88bb033
4
+ data.tar.gz: 1a5bfa383d83bd438721fb00391d95bc21765fdabefbf410e3eb4cde17d1d6ed
5
+ SHA512:
6
+ metadata.gz: '0763641083471eef9913c86d1333add5c26bcb7533ed4b64505012d458ce67381cd9aaac6d3b40a09d95e1413e33b7aff7454426f5f2ed0240b9bbb3819f03b6'
7
+ data.tar.gz: 27fdf6c50924c4d299f94df654c026c6097a262f5bfa174e055fe5ce5842d719d3ad3940a80d3599fe3d0ff66aac3fea3aa306926a75e574ce2da6eb61af6e84
@@ -0,0 +1,10 @@
1
+ name: Check Changelog
2
+ on: [pull_request]
3
+ jobs:
4
+ build:
5
+ runs-on: ubuntu-latest
6
+ steps:
7
+ - uses: actions/checkout@v1
8
+ - name: Check that CHANGELOG is touched
9
+ run: |
10
+ cat $GITHUB_EVENT_PATH | jq .pull_request.title | grep -i '\[\(\(changelog skip\)\|\(ci skip\)\)\]' || git diff remotes/origin/${{ github.base_ref }} --name-only | grep CHANGELOG.md
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ .DS_Store
2
+ *.gem
3
+ /test/rails_app/tmp/*
4
+ /test/rails_app/log/*
5
+ *.sqlite3
6
+
7
+ Gemfile.lock
8
+ gemfiles/*.lock
data/.gitlab-ci.yml ADDED
@@ -0,0 +1,56 @@
1
+ .test-template: &test
2
+ before_script:
3
+ - ruby -v
4
+ - git config --global user.email "test@example.com"
5
+ - gem install bundler --no-document
6
+ - bundle install -j $(nproc)
7
+ script:
8
+ - bundle exec rake test
9
+
10
+ ruby-2.5-rails-5.1:
11
+ image: "ruby:2.5"
12
+ variables:
13
+ BUNDLE_GEMFILE: "$CI_PROJECT_DIR/gemfiles/rails_5_1.gemfile"
14
+ <<: *test
15
+
16
+ ruby-2.5-rails-5.2:
17
+ image: "ruby:2.5"
18
+ variables:
19
+ BUNDLE_GEMFILE: "$CI_PROJECT_DIR/gemfiles/rails_5_2.gemfile"
20
+ <<: *test
21
+
22
+ ruby-2.5-rails-6.0:
23
+ image: "ruby:2.5"
24
+ variables:
25
+ BUNDLE_GEMFILE: "$CI_PROJECT_DIR/gemfiles/rails_6_0.gemfile"
26
+ <<: *test
27
+
28
+ ruby-2.5-rails-git:
29
+ image: "ruby:2.5"
30
+ variables:
31
+ BUNDLE_GEMFILE: "$CI_PROJECT_DIR/gemfiles/rails_git.gemfile"
32
+ <<: *test
33
+
34
+ ruby-2.6-rails-5.1:
35
+ image: "ruby:2.6"
36
+ variables:
37
+ BUNDLE_GEMFILE: "$CI_PROJECT_DIR/gemfiles/rails_5_1.gemfile"
38
+ <<: *test
39
+
40
+ ruby-2.6-rails-5.2:
41
+ image: "ruby:2.6"
42
+ variables:
43
+ BUNDLE_GEMFILE: "$CI_PROJECT_DIR/gemfiles/rails_5_2.gemfile"
44
+ <<: *test
45
+
46
+ ruby-2.6-rails-6.0:
47
+ image: "ruby:2.6"
48
+ variables:
49
+ BUNDLE_GEMFILE: "$CI_PROJECT_DIR/gemfiles/rails_6_0.gemfile"
50
+ <<: *test
51
+
52
+ ruby-2.6-rails-git:
53
+ image: "ruby:2.6"
54
+ variables:
55
+ BUNDLE_GEMFILE: "$CI_PROJECT_DIR/gemfiles/rails_git.gemfile"
56
+ <<: *test
data/.travis.yml ADDED
@@ -0,0 +1,18 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.5.5
4
+ - 2.6.3
5
+ - ruby-head
6
+
7
+ gemfile:
8
+ - gemfiles/rails_5_1.gemfile
9
+ - gemfiles/rails_5_2.gemfile
10
+ - gemfiles/rails_6_0.gemfile
11
+ - gemfiles/rails_git.gemfile
12
+
13
+ before_install:
14
+ - gem install bundler
15
+
16
+ matrix:
17
+ allow_failures:
18
+ - rvm: ruby-head
data/Appraisals ADDED
@@ -0,0 +1,26 @@
1
+ # -*- mode: ruby -*-
2
+ # vi: set ft=ruby :
3
+
4
+ appraise "rails-3-2" do
5
+ gem "rails", "~> 3.2.0"
6
+ end
7
+
8
+ appraise "rails-4-0" do
9
+ gem "rails", "~> 4.0.0"
10
+ end
11
+
12
+ appraise "rails-4-1" do
13
+ gem "rails", "~> 4.1.0"
14
+ end
15
+
16
+ appraise "rails-4-2" do
17
+ gem "rails", "~> 4.2.0"
18
+ end
19
+
20
+ appraise "rails-5-0" do
21
+ gem "rails", "~> 5.0.0"
22
+ end
23
+
24
+ appraise "rails-5-1" do
25
+ gem "rails", "~> 5.1.0"
26
+ end
data/CHANGELOG.md ADDED
@@ -0,0 +1,105 @@
1
+ ## master (unreleased)
2
+
3
+ - Fix bug with `Kernel#require` patch when Zeitwerk is enabled
4
+
5
+ ## 1.6.0
6
+
7
+ - Added the `perf:app` command to compare commits within the same application. (https://github.com/schneems/derailed_benchmarks/pull/157)
8
+ - Allow Rails < 7 and 1.0 <= Thor < 2 (https://github.com/schneems/derailed_benchmarks/pull/168)
9
+
10
+ ## 1.5.0
11
+
12
+ - Test `perf:library` results against 99% confidence interval in addition to 95% (https://github.com/schneems/derailed_benchmarks/pull/165)
13
+ - Change default, `perf:library` tests do not stop automatically any more (https://github.com/schneems/derailed_benchmarks/pull/164)
14
+
15
+ ## 1.4.4
16
+
17
+ - Fix alignment of deicmals in output (https://github.com/schneems/derailed_benchmarks/pull/161)
18
+
19
+ ## 1.4.3
20
+
21
+ - perf:library now uses median instead of average (https://github.com/schneems/derailed_benchmarks/pull/160)
22
+
23
+ ## 1.4.2
24
+
25
+ - Fixed syntax error that resulted in ensure end error inside tasks.rb for older rubies (https://github.com/schneems/derailed_benchmarks/pull/155)
26
+ - Fix case in perf:library where the same SHA could be tested against itself (https://github.com/schneems/derailed_benchmarks/pull/153)
27
+
28
+ ## 1.4.1
29
+
30
+ - Rake dependency now allows for Rake 13 (https://github.com/schneems/derailed_benchmarks/pull/151)
31
+
32
+ ## 1.4.0
33
+
34
+ - Allow configuration of `perf:ips` benchmark.
35
+ - Fix bug with `require_relative` [#142](https://github.com/schneems/derailed_benchmarks/pull/142)
36
+ - Introduce `perf:library` to profile patches to libraries (like Rails) [#135](https://github.com/schneems/derailed_benchmarks/pull/135), [#139](https://github.com/schneems/derailed_benchmarks/pull/139), [#140](https://github.com/schneems/derailed_benchmarks/pull/140), [#141](https://github.com/schneems/derailed_benchmarks/pull/141)
37
+
38
+ ## 1.3.6
39
+
40
+ - `require_relative` is now measured [commit](https://github.com/schneems/derailed_benchmarks/commit/af11bcc46a4fa24f79e4897a51034927a56e077e)
41
+ - Fix bug preventing a specific Rails 6 file from being loaded (https://github.com/schneems/derailed_benchmarks/pull/134)
42
+ - `exit(1)` is called instead of raise (https://github.com/schneems/derailed_benchmarks/pull/127)
43
+
44
+ ## [1.3.5]
45
+
46
+ - Output of `test` now emits the word "derailed" for easier grepping.
47
+ - Fix "already initialized constant" warning
48
+
49
+ ## [1.3.4]
50
+
51
+ - Allow for "warming up tasks" via WARM_COUNT env var #119
52
+
53
+ ## [1.3.3]
54
+
55
+ - Make all paths added to $LOAD_PATH absolute instead of relative to allow for use with apps that use bootsnap.
56
+
57
+ ## [1.3.2]
58
+
59
+ - Allow for use with Rack 11.
60
+
61
+
62
+ ## [1.3.1]
63
+
64
+ - Allow for use with Rack 11.
65
+
66
+
67
+ ## [1.3.0] - 2015-01-07
68
+
69
+ - Allow environment variable to skip Active Record setup.
70
+ - Allow Rack 2 to work with Derailed.
71
+
72
+ ## [1.1.3] - 2015-10-15
73
+
74
+ - Update docs
75
+
76
+ ## [1.1.2] - 2015-10-05
77
+
78
+ - Added ability to use TEST_COUNT environment variable with `perf:heap`.
79
+
80
+ ## [1.1.1] - 2015-10-01
81
+
82
+ - Added ability to create a heap dump `perf:heap`.
83
+
84
+ ## [1.1.0] - 2015-09-09
85
+
86
+ - Set custom auth user using a lambda in perf.rake
87
+ - Changed `perf:ram_over_time` changed to `perf:mem_over_time`
88
+ - Fixed gem warnings
89
+
90
+ ## [1.0.1] - 2015-06-20
91
+
92
+ - `bundle:mem` and similar tasks now keep track of duplicate requires and display them along side of memory requirements. This makes it easier to identify where components are used by multiple libraries
93
+ - Add rake to gemspec which gets rid of `Unresolved specs during Gem::Specification.reset:` warning
94
+ - Outputs of memory are now done in [mebibytes](https://en.wikipedia.org/wiki/Mebibyte), a more accurate unit for the value we're measuring (hint: it's what you think MB is).
95
+
96
+ ## [1.0.0] - 2015-05-14
97
+
98
+ - Added `derailed` command line utility. Can be used with just a Gemfile using command `$ derailed bundle:mem` and `$ derailed bundle:objects`. All existing Rake tasks can now be called with `$ derailed exec` such as `$ derailed exec perf:mem`.
99
+ - Changed memory_profiler task to be `perf:objects` instead of `perf:mem`.
100
+ - Changed boot time memory measurement to `perf:mem` instead of `perf:require_bench`
101
+ - Released seperate [derailed](https://github.com/schneems/derailed) gem that is a wrapper for this gem. I.e. installing that gem installs this one. Easier to remember, less words to type. Also means there's no colision using the `derailed` namespace for executables inside of the `derailed_benchmarks`.
102
+
103
+ ## [0.0.0] - 2014-08-15
104
+
105
+ - Initial release
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :development, :test do
6
+ gem "sqlite3", :platform => [:ruby, :mswin, :mingw]
7
+ gem "activerecord-jdbcsqlite3-adapter", '~> 1.3.13', :platform => :jruby
8
+ gem "test-unit", "~> 3.0"
9
+ end
data/README.md ADDED
@@ -0,0 +1,692 @@
1
+ This was forked to include the patch in https://github.com/schneems/derailed_benchmarks/pull/170
2
+
3
+ ## Derailed Benchmarks
4
+
5
+ A series of things you can use to benchmark a Rails or Ruby app.
6
+
7
+ ![](http://media.giphy.com/media/lfbxexWy71b6U/giphy.gif)
8
+
9
+ [![Build Status](https://travis-ci.org/schneems/derailed_benchmarks.svg)](https://travis-ci.org/schneems/derailed_benchmarks)
10
+ [![Help Contribute to Open Source](https://www.codetriage.com/schneems/derailed_benchmarks/badges/users.svg)](https://www.codetriage.com/schneems/derailed_benchmarks)
11
+
12
+ ## Compatibility/Requirements
13
+
14
+ This gem has been tested and is known to work with Rails 3.2+ using Ruby
15
+ 2.1+. Some commands __may__ work on older versions of Ruby, but not all commands are supported.
16
+
17
+ For some benchmarks, not all, you'll need to verify you have a working version of curl on your OS:
18
+
19
+ ```
20
+ $ which curl
21
+ /usr/bin/curl
22
+ $ curl -V
23
+ curl 7.37.1 #...
24
+ ```
25
+
26
+ ## Install
27
+
28
+ Put this in your gemfile:
29
+
30
+ ```ruby
31
+ gem 'derailed_benchmarks', group: :development
32
+ ```
33
+
34
+ Then run `$ bundle install`.
35
+
36
+ While executing your commands you may need to use `bundle exec` before typing the command.
37
+
38
+ To use all profiling methods available also add:
39
+
40
+ ```ruby
41
+ gem 'stackprof', group: :development
42
+ ```
43
+
44
+ You must be using Ruby 2.1+ to install these libraries. If you're on an older version of Ruby, what are you waiting for?
45
+
46
+ ## Use
47
+
48
+ There are two ways to benchmark an app. Derailed can either try to boot your web app and run requests against it while benchmarking, or it can statically give you more information about the dependencies that are in your Gemfile. Booting your app will always be more accurate, but if you cannot get your app to run in production locally, you'll still find the static information useful.
49
+
50
+ ## Static Benchmarking
51
+
52
+ This section covers how to get memory information from your Gemfile without having to boot your app.
53
+
54
+ All commands in this section will begin with `$ derailed bundle:`
55
+
56
+ For more information on the relationship between memory and performance please read/watch [How Ruby Uses Memory](http://www.schneems.com/2015/05/11/how-ruby-uses-memory.html).
57
+
58
+ ### Memory used at Require time
59
+
60
+ Each gem you add to your project can increase your memory at boot. You can get visibility into the total memory used by each gem in your Gemfile by running:
61
+
62
+ ```
63
+ $ bundle exec derailed bundle:mem
64
+ ```
65
+
66
+ This will load each of your gems in your Gemfile and see how much memory they consume when they are required. For example if you're using the `mail` gem. The output might look like this
67
+
68
+ ```
69
+ $ bundle exec derailed bundle:mem
70
+ TOP: 54.1836 MiB
71
+ mail: 18.9688 MiB
72
+ mime/types: 17.4453 MiB
73
+ mail/field: 0.4023 MiB
74
+ mail/message: 0.3906 MiB
75
+ action_view/view_paths: 0.4453 MiB
76
+ action_view/base: 0.4336 MiB
77
+ ```
78
+
79
+ _Aside: A "MiB", which is the [IEEE] and [IEC] symbol for Mebibyte, is 2<sup>20</sup> bytes / 1024 Kibibytes (which are in turn 1024 bytes)._
80
+
81
+ [IEEE]: https://en.wikipedia.org/wiki/IEEE_1541-2002
82
+ [IEC]: https://en.wikipedia.org/wiki/IEC_80000-13
83
+
84
+ Here we can see that `mail` uses 18MiB, with the majority coming from `mime/types`. You can use this information to prune out large dependencies you don't need. Also if you see a large memory use by a gem that you do need, please open up an issue with that library to let them know (be sure to include reproduction instructions). Hopefully as a community we can identify memory hotspots and reduce their impact. Before we can fix performance problems, we need to know where those problems exist.
85
+
86
+ By default this task will only return results from the `:default` and `"production"` groups. If you want a different group you can run with.
87
+
88
+ ```
89
+ $ bundle exec derailed bundle:mem development
90
+ ```
91
+
92
+ You can use `CUT_OFF=0.3` to only show files that have above a certain memory usage, this can be used to help eliminate noise.
93
+
94
+ Note: This method won't include files in your own app, only items in your Gemfile. For that you'll need to use `bundle exec derailed exec mem`. See below for more info.
95
+
96
+ The same file may be required by several libraries, since Ruby only requires files once, the cost is only associated with the first library to require a file. To make this more visible duplicate entries will list all the parents they belong to. For example both `mail` and `fog` require `mime/types. So it may show up something like this in your app:
97
+
98
+ ```
99
+ $ bundle exec derailed bundle:mem
100
+ TOP: 54.1836 MiB
101
+ mail: 18.9688 MiB
102
+ mime/types: 17.4453 MiB (Also required by: fog/storage)
103
+ mail/field: 0.4023 MiB
104
+ mail/message: 0.3906 MiB
105
+ ```
106
+
107
+ That way you'll know that simply removing the top level library (mail) would not result in a memory reduction. The output is truncated after the first two entries:
108
+
109
+
110
+ ```
111
+ fog/core: 0.9844 MiB (Also required by: fog/xml, fog/json, and 48 others)
112
+ fog/rackspace: 0.957 MiB
113
+ fog/joyent: 0.7227 MiB
114
+ fog/joyent/compute: 0.7227 MiB
115
+ ```
116
+
117
+ If you want to see everything that requires `fog/core` you can run `CUT_OFF=0 bundle exec derailed bundle:mem` to get the full output that you can then grep through manually.
118
+
119
+ Update: While `mime/types` looks horrible in these examples, it's been fixed. You can add this to the top of your gemfile for free memory:
120
+
121
+ ```ruby
122
+ gem 'mime-types', [ '~> 2.6', '>= 2.6.1' ], require: 'mime/types/columnar'
123
+ ```
124
+
125
+ ### Objects created at Require time
126
+
127
+ To get more info about the objects, using [memory_profiler](https://github.com/SamSaffron/memory_profiler), created when your dependencies are required you can run:
128
+
129
+ ```
130
+ $ bundle exec derailed bundle:objects
131
+ ```
132
+
133
+ This will output detailed information about objects created while your dependencies are loaded
134
+
135
+ ```
136
+ Measuring objects created by gems in groups [:default, "production"]
137
+ Total allocated 433895
138
+ Total retained 100556
139
+
140
+ allocated memory by gem
141
+ -----------------------------------
142
+ 24369241 activesupport-4.2.1
143
+ 15560550 mime-types-2.4.3
144
+ 8103432 json-1.8.2
145
+ ```
146
+
147
+ Once you identify a gem that creates a large amount of memory using `$ bundle exec derailed bundle:mem` you can pull that gem into it's own Gemfile and run `$ bundle exec derailed bundle:objects` to get detailed information about it. This information can be used by contributors and library authors to identify and eliminate object creation hotspots.
148
+
149
+
150
+ By default this task will only return results from the `:default` and `"production"` groups. If you want a different group you can run with.
151
+
152
+ ```
153
+ $ bundle exec derailed bundle:objects development
154
+ ```
155
+
156
+ Note: This method won't include files in your own app, only items in your Gemfile. For that you'll need to use `bundle exec derailed exec objects`. See below for more info.
157
+
158
+
159
+ ## Dynamic app Benchmarking
160
+
161
+ This benchmarking will attempt to boot your Rails app and run benchmarks against it. Unlike the static benchmarking with `$ bundle exec derailed bundle:*` these will include information about your specific app. The pro is you'll get more information and potentially identify problems in your app code, the con is that it requires you to be able to boot and run your application in a `production` environment locally, which for some apps is non-trivial.
162
+
163
+ You may want to check out [mini-profiler](https://github.com/MiniProfiler/rack-mini-profiler), here's a [mini-profiler walkthrough](http://www.justinweiss.com/articles/a-new-way-to-understand-your-rails-apps-performance/). It's great and does slightly different benchmarking than what you'll find here.
164
+
165
+ ### Running in Production Locally.
166
+
167
+ Before you want to attempt any dynamic benchmarks, you'll need to boot your app in `production` mode. We benchmark using `production` because it is close to your deployed performance. This section is more a collection of tips rather than a de-facto tutorial.
168
+
169
+ For starters try booting into a console:
170
+
171
+ ```
172
+ $ RAILS_ENV=production rails console
173
+ ```
174
+
175
+ You may get errors, complaining about not being able to connect to the `production` database. For this, you can either create a local database with the name of your production database, or you can copy the info from your `development` group to your `production` group in your `database.yml`.
176
+
177
+ You may be missing environment variables expected in `production` such as `SECRET_KEY_BASE`. For those you can either commit them to your `.env` file (if you're using one). Or add them directly to the command:
178
+
179
+ ```
180
+ $ SECRET_KEY_BASE=foo RAILS_ENV=production rails console
181
+ ```
182
+
183
+ Once you can boot a console in production, you'll need to be able to boot a server in production
184
+
185
+ ```
186
+ $ RAILS_ENV=production rails server
187
+ ```
188
+
189
+ You may need to disable enforcing SSL or other domain restrictions temporarily. If you do these, don't forget to add them back in before deploying any code (eek!).
190
+
191
+ You can get information from STDOUT if you're using `rails_12factor` gem, or from `log/production.log` by running
192
+
193
+ ```
194
+ $ tail -f log/production.log
195
+ ```
196
+
197
+ Once you've fixed all errors and you can run a server in production, you're almost there.
198
+
199
+ ### Running Derailed Exec
200
+
201
+ You can run commands against your app by running `$ derailed exec`. There are sections on setting up Rack and using authenticated requests below. You can see what commands are available by running:
202
+
203
+ ```
204
+ $ bundle exec derailed exec --help
205
+ $ derailed exec perf:allocated_objects # outputs allocated object diff after app is called TEST_COUNT times
206
+ $ derailed exec perf:gc # outputs GC::Profiler.report data while app is called TEST_COUNT times
207
+ $ derailed exec perf:ips # iterations per second
208
+ $ derailed exec perf:mem # show memory usage caused by invoking require per gem
209
+ $ derailed exec perf:objects # profiles ruby allocation
210
+ $ derailed exec perf:mem_over_time # outputs memory usage over time
211
+ $ derailed exec perf:test # hits the url TEST_COUNT times
212
+ ```
213
+
214
+ Instead of going over each command we'll look at common problems and which commands are best used to diagnose them. Later on we'll cover all of the environment variables you can use to configure derailed benchmarks in it's own section.
215
+
216
+
217
+ ### Is my app leaking memory?
218
+
219
+ If your app appears to be leaking ever increasing amounts of memory, you'll want to first verify if it's an actual unbound "leak" or if it's just using more memory than you want. A true memory leak will increase memory use forever, most apps will increase memory use until they hit a "plateau". To diagnose this you can run:
220
+
221
+ ```
222
+ $ bundle exec derailed exec perf:mem_over_time
223
+ ```
224
+
225
+ This will boot your app and hit it with requests and output the memory to stdout (and a file under ./tmp). It may look like this:
226
+
227
+ ```
228
+ $ bundle exec derailed exec perf:mem_over_time
229
+ Booting: production
230
+ Endpoint: "/"
231
+ PID: 78675
232
+ 103.55078125
233
+ 178.45703125
234
+ 179.140625
235
+ 180.3671875
236
+ 182.1875
237
+ 182.55859375
238
+ # ...
239
+ 183.65234375
240
+ 183.26171875
241
+ 183.62109375
242
+ ```
243
+
244
+ Here we can see that while the memory use is increasing, it levels off around 183 MiB. You'll want to run this task using ever increasing values of `TEST_COUNT=` for example
245
+
246
+ ```
247
+ $ TEST_COUNT=5000 bundle exec derailed exec perf:mem_over_time
248
+ $ TEST_COUNT=10_000 bundle exec derailed exec perf:mem_over_time
249
+ $ TEST_COUNT=20_000 bundle exec derailed exec perf:mem_over_time
250
+ ```
251
+
252
+ Adjust your counts appropriately so you can get results in a reasonable amount of time. If your memory never levels off, congrats! You've got a memory leak! I recommend copying and pasting values from the file generated into google docs and graphing it so you can get a better sense of the slope of your line.
253
+
254
+ If you don't want it to generate a tmp file with results run with `SKIP_FILE_WRITE=1`.
255
+
256
+ If you're pretty sure that there's a memory leak, but you can't confirm it using this method. Look at the environment variable options below, you can try hitting a different endpoint etc.
257
+
258
+ ## Dissecting a Memory Leak
259
+
260
+ If you've identified a memory leak, or you simply want to see where your memory use is coming from you'll want to use
261
+
262
+ ```
263
+ $ bundle exec derailed exec perf:objects
264
+ ```
265
+
266
+ This task hits your app and uses memory_profiler to see where objects are created. You'll likely want to run once, then run it with a higher `TEST_COUNT` so that you can see hotspots where objects are created on __EVERY__ request versus just maybe on the first.
267
+
268
+
269
+ ```
270
+ $ TEST_COUNT=10 bundle exec derailed exec perf:objects
271
+ ```
272
+
273
+ This is an expensive operation, so you likely want to keep the count lowish. Once you've identified a hotspot read [how ruby uses memory](http://www.sitepoint.com/ruby-uses-memory/) for some tips on reducing object allocations.
274
+
275
+ This is similar to `$ bundle exec derailed bundle:objects` however it includes objects created at runtime. It's much more useful for actual production performance debugging, the other is more useful for library authors to debug.
276
+
277
+ ## I want a Heap Dump
278
+
279
+ If you're still struggling with runtime memory you can generate a heap dump that can later be analyzed using [heap_inspect](https://github.com/schneems/heapy).
280
+
281
+ ```
282
+ $ bundle exec derailed exec perf:heap
283
+ Booting: production
284
+ Heap file generated: "tmp/2015-10-01T12:31:03-05:00-heap.dump"
285
+
286
+ Analyzing Heap
287
+ ==============
288
+ Generation: 0 object count: 209307
289
+ Generation: 35 object count: 31236
290
+ Generation: 36 object count: 36705
291
+ Generation: 37 object count: 1301
292
+ Generation: 38 object count: 8
293
+
294
+ Try uploading "tmp/2015-10-01T12:31:03-05:00-heap.dump" to http://tenderlove.github.io/heap-analyzer/
295
+ ```
296
+
297
+ For more help on getting data from a heap dump see
298
+
299
+ ```
300
+ $ heapy --help
301
+ ```
302
+
303
+ ### Memory Is large at boot.
304
+
305
+ Ruby memory typically goes in one direction, up. If your memory is large when you boot the application it will likely only increase. In addition to debugging memory retained from dependencies obtained while running `$ derailed bundle:mem` you'll likely want to see how your own files contribute to memory use.
306
+
307
+ This task does essentially the same thing, however it hits your app with one request to ensure that any last minute `require`-s have been called. To execute you can run:
308
+
309
+
310
+ ```
311
+ $ bundle exec derailed exec perf:mem
312
+
313
+ TOP: 54.1836 MiB
314
+ mail: 18.9688 MiB
315
+ mime/types: 17.4453 MiB
316
+ mail/field: 0.4023 MiB
317
+ mail/message: 0.3906 MiB
318
+ action_view/view_paths: 0.4453 MiB
319
+ action_view/base: 0.4336 MiB
320
+ ```
321
+
322
+ You can use `CUT_OFF=0.3` to only show files that have above a certain memory usage, this can be used to help eliminate noise.
323
+
324
+ If your application code is extremely large at boot consider using `$ derailed exec perf:objects` to debug low level object creation.
325
+
326
+ ## My app is Slow
327
+
328
+ Well...aren't they all. If you've already looked into decreasing object allocations, you'll want to look at where your app is spending the most amount of code. Once you know that, you'll know where to spend your time optimising.
329
+
330
+ One technique is to use a "sampling" stack profiler. This type of profiling looks at what method is being executed at a given interval and records it. At the end of execution it counts all the times a given method was being called and shows you the percent of time spent in each method. This is a very low overhead method to looking into execution time. Ruby 2.1+ has this available in gem form it's called [stackprof](https://github.com/tmm1/stackprof). As you guessed you can run this with derailed benchmarks, first add it to your gemfile `gem "stackprof", group: :development` then execute:
331
+
332
+ ```
333
+ $ bundle exec derailed exec perf:stackprof
334
+ ==================================
335
+ Mode: cpu(1000)
336
+ Samples: 16067 (1.07% miss rate)
337
+ GC: 2651 (16.50%)
338
+ ==================================
339
+ TOTAL (pct) SAMPLES (pct) FRAME
340
+ 1293 (8.0%) 1293 (8.0%) block in ActionDispatch::Journey::Formatter#missing_keys
341
+ 872 (5.4%) 872 (5.4%) block in ActiveSupport::Inflector#apply_inflections
342
+ 935 (5.8%) 802 (5.0%) ActiveSupport::SafeBuffer#safe_concat
343
+ 688 (4.3%) 688 (4.3%) Temple::Utils#escape_html
344
+ 578 (3.6%) 578 (3.6%) ActiveRecord::Attribute#initialize
345
+ 3541 (22.0%) 401 (2.5%) ActionDispatch::Routing::RouteSet#url_for
346
+ 346 (2.2%) 346 (2.2%) ActiveSupport::SafeBuffer#initialize
347
+ 298 (1.9%) 298 (1.9%) ThreadSafe::NonConcurrentCacheBackend#[]
348
+ 227 (1.4%) 227 (1.4%) block in ActiveRecord::ConnectionAdapters::PostgreSQLAdapter#exec_no_cache
349
+ 218 (1.4%) 218 (1.4%) NewRelic::Agent::Instrumentation::Event#initialize
350
+ 1102 (6.9%) 213 (1.3%) ActiveSupport::Inflector#apply_inflections
351
+ 193 (1.2%) 193 (1.2%) ActionDispatch::Routing::RouteSet::NamedRouteCollection::UrlHelper#deprecate_string_options
352
+ 173 (1.1%) 173 (1.1%) ActiveSupport::SafeBuffer#html_safe?
353
+ 308 (1.9%) 171 (1.1%) NewRelic::Agent::Instrumentation::ActionViewSubscriber::RenderEvent#metric_name
354
+ 159 (1.0%) 159 (1.0%) block in ActiveRecord::Result#hash_rows
355
+ 358 (2.2%) 153 (1.0%) ActionDispatch::Routing::RouteSet::Generator#initialize
356
+ 153 (1.0%) 153 (1.0%) ActiveRecord::Type::String#cast_value
357
+ 192 (1.2%) 143 (0.9%) ActionController::UrlFor#url_options
358
+ 808 (5.0%) 127 (0.8%) ActiveRecord::LazyAttributeHash#[]
359
+ 121 (0.8%) 121 (0.8%) PG::Result#values
360
+ 120 (0.7%) 120 (0.7%) ActionDispatch::Journey::Router::Utils::UriEncoder#escape
361
+ 2478 (15.4%) 117 (0.7%) ActionDispatch::Journey::Formatter#generate
362
+ 115 (0.7%) 115 (0.7%) NewRelic::Agent::Instrumentation::EventedSubscriber#event_stack
363
+ 114 (0.7%) 114 (0.7%) ActiveRecord::Core#init_internals
364
+ 263 (1.6%) 110 (0.7%) ActiveRecord::Type::Value#type_cast
365
+ 8520 (53.0%) 102 (0.6%) ActionView::CompiledTemplates#_app_views_repos__repo_html_slim__2939326833298152184_70365772737940
366
+ ```
367
+
368
+ From here you can dig into individual methods.
369
+
370
+ ## Is this perf change faster?
371
+
372
+ Micro benchmarks might tell you at the code level how much faster something is, but what about the overall application speed. If you're trying to figure out how effective a performance change is to your application, it is useful to compare it to your existing app performance. To help you with that you can use:
373
+
374
+ ```
375
+ $ bundle exec derailed exec perf:ips
376
+ Endpoint: "/"
377
+ Calculating -------------------------------------
378
+ ips 1.000 i/100ms
379
+ -------------------------------------------------
380
+ ips 3.306 (± 0.0%) i/s - 17.000
381
+ ```
382
+
383
+ This will hit an endpoint in your application using [benchmark-ips](https://github.com/evanphx/benchmark-ips). In "iterations per second" a higher value is always better. You can run your code change several times using this method, and then run your "baseline" codebase (without your changes) to see how it affects your overall performance. You'll want to run and record the results several times (including the std deviation) so you can help eliminate noise. Benchmarking is hard, this technique isn't perfect but it's definitely better than nothing.
384
+
385
+ If you care you can also run pure benchmark (without ips):
386
+
387
+ ```
388
+ $ bundle exec derailed exec perf:test
389
+ ```
390
+
391
+ But I wouldn't, benchmark-ips is a better measure.
392
+
393
+ ### Configuring `benchmark-ips`
394
+
395
+ The `benchmark-ips` gem allows for a number of test run customizations, and `derailed_benchmarks` exposes a few of them via environment variables.
396
+
397
+ - `IPS_WARMUP`: number of seconds spent warming up the app, defaullt is `2`
398
+ - `IPS_TIME`: number of seconds to run ips benchmark for after warm up, defaullt is `5`
399
+ - `IPS_SUITE`: custom suite to use to run test
400
+ - `IPS_ITERATIONS`: number of times to run the test, displaying that last result, defaullt is `1`
401
+
402
+ ## I made a patch to to Rails how can I tell if it made my Rails app faster and test for statistical significance
403
+
404
+ When you're trying to submit a performance patch to rails/rails then they'll likely ask you for a benchmark. While you can sometimes provide a microbenchmark, a real world full stack request/response test is the gold standard.
405
+
406
+ That's what this section is about. You'll need a rails app, ideally one you can open source (see [example apps](http://codetriage.com/example_app) if you need inspiration for extracting your private code into something external).
407
+
408
+ Then you'll need to fork rails and make a branch. Then point your rails app to your branch in your gemfile
409
+
410
+ ```
411
+ gem 'rails', github: "<github username>/rails", branch: "<your branch name>"
412
+ ```
413
+
414
+ or point it at your local copy:
415
+
416
+ ```
417
+ gem 'rails', path: "<path/to/your/local/copy/rails>"
418
+ ```
419
+
420
+ To run your tests within the context of your current app/repo:
421
+
422
+ ```
423
+ $ bundle exec derailed exec perf:app
424
+ ```
425
+
426
+ This will automatically test the two latest commits of your library/current directory.
427
+
428
+ If you'd like to test the Rails library instead, make sure that `ENV[DERAILED_PATH_TO_LIBRARY]` is unset.
429
+
430
+ ```
431
+ $ bundle exec derailed exec perf:library
432
+ ```
433
+
434
+ This will automatically test the two latest commits of Rails.
435
+
436
+ If you would also like to compare against different SHAs you can manually specify them:
437
+
438
+ ```
439
+ $ SHAS_TO_TEST="7b4d80cb373e,13d6aa3a7b70" bundle exec derailed exec perf:library
440
+ ```
441
+
442
+ Use a comma to seperate your branch names with the `SHAS_TO_TEST` env var, or omit the env var to use the last 2 git commits.
443
+
444
+ If you only include one SHA, then derailed will grab the latest commit and compare it to that SHA.
445
+
446
+ These tests might take a along time to run so the output is stored on disk incase you want to see them in the future, they're at `tmp/compare_branches/<timestamp>` and labeled with the same names as your commits.
447
+
448
+ When the test is done it will output which commit "won" and by how much:
449
+
450
+ ```
451
+ ❤️ ❤️ ❤️ (Statistically Significant) ❤️ ❤️ ❤️
452
+
453
+ [7b4d80cb37] "1.8x Faster Partial Caching - Faster Cache Keys" - (10.9711965 seconds)
454
+ FASTER by:
455
+ 1.0870x [older/newer]
456
+ 8.0026% [(older - newer) / older * 100]
457
+ [13d6aa3a7b] "Merge pull request #36284 from kamipo/fix_eager_loading_with_string_joins" - (11.9255485 seconds)
458
+ ```
459
+
460
+ You can provide this to the Rails team along with the example app you used to benchmark (so they can independently verify if needed).
461
+
462
+ Generally performance patches have to be weighted in terms of how much they help versus how large/difficult/gnarly the patch is. If the above example was a really tiny patch and it was in a common component, then half a percent might be a justafiable increase. If it was a huge re-write then it's likely going to be closed. In general I tend to not submit patches unless I'm seeing `>= 1%` performance increases.
463
+
464
+ You can use this to test changes in other libraries that aren't rails, you just have to tell it the path to the library you want to test against with the `DERAILED_PATH_TO_LIBRARY` env var.
465
+
466
+ > To get the best results before running tests you should close all programs on your laptop, turn on a program to prevent your laptop from going to sleep (or increase your sleep timer). Make sure it's plugged into a power outlet and go grab a cup of coffee. If you do anything on your laptop while this test is running you risk the chance of skewing your results.
467
+
468
+ As the test is executing, intermediate results will be printed every 50 iterations.
469
+
470
+ ## Environment Variables
471
+
472
+ All the tasks accept configuration in the form of environment variables.
473
+
474
+ ### Increasing or decreasing test count `TEST_COUNT`
475
+
476
+ For tasks that are run a number of times you can set the number using `TEST_COUNT` for example:
477
+
478
+ ```
479
+ $ TEST_COUNT=100_000 bundle exec derailed exec perf:test
480
+ ```
481
+
482
+ ### Warming up your app before measuring with `WARM_COUNT`
483
+
484
+ When you are measuring the long term performance of an application, especially if you're using jit you may want to let the application "warm up" without measuring this time. To allow for this you can specify `WARM_COUNT` and the application will be called that number of times before any measurements are taken.
485
+
486
+ ```
487
+ $ WARM_COUNT=5_000 bundle exec derailed exec perf:test
488
+ Warming up app: 5000 times
489
+ # ...
490
+ ```
491
+
492
+ ### Hitting a different endpoint with `PATH_TO_HIT`
493
+
494
+ By default tasks will hit your homepage `/`. If you want to hit a different url use `PATH_TO_HIT` for example if you wanted to go to `users/new` you can execute:
495
+
496
+ ```
497
+ $ PATH_TO_HIT=/users/new bundle exec derailed exec perf:mem
498
+ ```
499
+
500
+ This method accepts a full uri. For example, allowing you to hit a subdomain endpoint:
501
+
502
+ ```
503
+ $ PATH_TO_HIT=http://subdomain.lvh.me:3000/users/new bundle exec derailed exec perf:mem
504
+ ```
505
+
506
+ Beware that you cannot combine a full uri with `USE_SERVER`.
507
+
508
+ ### Setting HTTP headers
509
+
510
+ You can specify HTTP headers by setting `HTTP_<header name>` variables. Example:
511
+
512
+ ```
513
+ $ HTTP_AUTHORIZATION="Basic YWRtaW46c2VjcmV0\n" \
514
+ HTTP_USER_AGENT="Mozilla/5.0" \
515
+ PATH_TO_HIT=/foo_secret bundle exec derailed exec perf:ips
516
+ ```
517
+
518
+ ### Using a real web server with `USE_SERVER`
519
+
520
+ All tests are run without a webserver (directly using `Rack::Mock` by default), if you want to use a webserver set `USE_SERVER` to a Rack::Server compliant server, such as `webrick`.
521
+
522
+ ```
523
+ $ USE_SERVER=webrick bundle exec derailed exec perf:mem
524
+ ```
525
+
526
+ Or
527
+
528
+ ```
529
+ $ USE_SERVER=puma bundle exec derailed exec perf:mem
530
+ ```
531
+
532
+ This boots a webserver and hits it using `curl` instead of in memory. This is useful if you think the performance issue is related to your webserver.
533
+
534
+ Note: this plugs in the given webserver directly into rack, it doesn't use any `puma.config` file etc. that you have set-up. If you want to do this, i'm open to suggestions on how (and pull requests)
535
+
536
+ ### Excluding ActiveRecord
537
+
538
+ By default, derailed will load ActiveRecord if the gem is included as a dependency. It is included by default, if you just include the `rails` gem. If you are using a different ORM, you will either need to only include the `railties` gem, or set the `DERAILED_SKIP_ACTIVE_RECORD` flag.
539
+
540
+ ```
541
+ $ DERAILED_SKIP_ACTIVE_RECORD=true
542
+ ```
543
+
544
+ ### Running in a different environment
545
+
546
+ Tests run against the production environment by default, but it's easy to
547
+ change this if your app doesn't run locally with `RAILS_ENV` set to
548
+ `production`. For example:
549
+
550
+ ```
551
+ $ RAILS_ENV=development bundle exec derailed exec perf:mem
552
+ ```
553
+
554
+ ## perf.rake
555
+
556
+ If you want to customize derailed, you'll need to create a `perf.rake` file at the root of the directory you're trying to benchmark.
557
+
558
+ It is possible to run benchmarks directly using rake
559
+
560
+ ```
561
+ $ cat << EOF > perf.rake
562
+ require 'bundler'
563
+ Bundler.setup
564
+
565
+ require 'derailed_benchmarks'
566
+ require 'derailed_benchmarks/tasks'
567
+ EOF
568
+ ```
569
+
570
+ The file should look like this:
571
+
572
+ ```
573
+ $ cat perf.rake
574
+ require 'bundler'
575
+ Bundler.setup
576
+
577
+ require 'derailed_benchmarks'
578
+ require 'derailed_benchmarks/tasks'
579
+ ```
580
+
581
+ This is done so the benchmarks will be loaded before your application, this is important for some benchmarks and less for others. This also prevents you from accidentally loading these benchmarks when you don't need them.
582
+
583
+ Then you can execute your commands via rake.
584
+
585
+ To find out the tasks available you can use `$ rake -f perf.rake -T` which essentially says use the file `perf.rake` and list all the tasks.
586
+
587
+ ```
588
+ $ rake -f perf.rake -T
589
+ ```
590
+
591
+ ## Rack Setup
592
+
593
+ Using Rails? You don't need to do anything special. If you're using Rack, you need to tell us how to boot your app. In your `perf.rake` file add a task:
594
+
595
+ ```ruby
596
+ namespace :perf do
597
+ task :rack_load do
598
+ DERAILED_APP = # your code here
599
+ end
600
+ end
601
+ ```
602
+
603
+ Set the constant `DERAILED_APP` to your Rack app. See [schneems/derailed_benchmarks#1](https://github.com/schneems/derailed_benchmarks/pull/1) for more info.
604
+
605
+ An example of setting this up could look like:
606
+
607
+
608
+ ```ruby
609
+ # perf.rake
610
+
611
+ require 'bundler'
612
+ Bundler.setup
613
+
614
+ require 'derailed_benchmarks'
615
+ require 'derailed_benchmarks/tasks'
616
+
617
+ namespace :perf do
618
+ task :rack_load do
619
+ require_relative 'lib/application'
620
+ DERAILED_APP = MyApplication::Routes
621
+ end
622
+ end
623
+ ```
624
+
625
+ ## Authentication
626
+
627
+ If you're trying to test an endpoint that has authentication you'll need to tell your task how to bypass that authentication. Authentication is controlled by the `DerailedBenchmarks.auth` object. There is a built in support for Devise. If you're using some other authentication method, you can write your own authentication strategy.
628
+
629
+ To enable authentication in a test run with:
630
+
631
+ ```
632
+ $ USE_AUTH=true bundle exec derailed exec perf:mem
633
+ ```
634
+
635
+ See below how to customize authentication.
636
+
637
+ ### Authentication with Devise
638
+
639
+ If you're using devise, there is a built in auth helper that will detect the presence of the devise gem and load automatically.
640
+
641
+ Create a `perf.rake` file at your root.
642
+
643
+ ```
644
+ $ cat perf.rake
645
+ ```
646
+
647
+ If you want you can customize the user that is logged in by setting that value in your `perf.rake` file.
648
+
649
+ ```ruby
650
+ DerailedBenchmarks.auth.user = -> { User.find_or_create!(twitter: "schneems") }
651
+ ```
652
+
653
+ You will need to provide a valid user, so depending on the validations you have in your `user.rb`, you may need to provide different parameters.
654
+
655
+ If you're trying to authenticate a non-user model, you'll need to write your own custom auth strategy.
656
+
657
+ ### Custom Authentication Strategy
658
+
659
+ To implement your own authentication strategy You will need to create a class that [inherits from auth_helper.rb](lib/derailed_benchmarks/auth_helper.rb). You will need to implement a `setup` and a `call` method. You can see an example of [how the devise auth helper was written](lib/derailed_benchmarks/auth_helpers/devise.rb) and [how it can be done for Clearance](https://gist.github.com/zavan/f4d34dd86bf825db549a0ac28c7e10d5). You can put this code in your `perf.rake` file.
660
+
661
+ ```ruby
662
+ class MyCustomAuth < DerailedBenchmarks::AuthHelper
663
+ def setup
664
+ # initialize code here
665
+ end
666
+
667
+ def call(env)
668
+ # log something in on each request
669
+ app.call(env)
670
+ end
671
+ end
672
+ ```
673
+
674
+ The devise strategy works by enabling test mode inside of the Rack request and inserting a stub user. You'll need to duplicate that logic for your own authentication scheme if you're not using devise.
675
+
676
+ Once you have your class, you'll need to set `DerailedBenchmarks.auth` to a new instance of your class. In your `perf.rake` file add:
677
+
678
+ ```ruby
679
+ DerailedBenchmarks.auth = MyCustomAuth.new
680
+ ```
681
+
682
+ Now on every request that is made with the `USE_AUTH` environment variable set, the `MyCustomAuth#call` method will be invoked.
683
+
684
+ ## License
685
+
686
+ MIT
687
+
688
+ ## Acknowledgements
689
+
690
+ Most of the commands are wrappers around other libraries, go check them out. Also thanks to [@tenderlove](https://twitter.com/tenderlove) as I cribbed some of the Rails init code in `$ rake perf:setup` from one of his projects.
691
+
692
+ kthksbye [@schneems](https://twitter.com/schneems)