easy-prof 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +3 -0
- data/.travis.yml +9 -0
- data/Gemfile +4 -0
- data/README.md +239 -0
- data/Rakefile +6 -31
- data/easy-prof.gemspec +27 -0
- data/lib/easy-prof.rb +1 -0
- data/lib/easy_prof.rb +7 -7
- data/lib/{easy_profiler → easy_prof}/action_controller_extensions.rb +0 -0
- data/lib/{easy_profiler → easy_prof}/configuration.rb +21 -11
- data/lib/{easy_profiler → easy_prof}/firebug_logger.rb +0 -0
- data/lib/{easy_profiler → easy_prof}/no_profile_instance.rb +0 -0
- data/lib/{easy_profiler → easy_prof}/profile.rb +9 -7
- data/lib/{easy_profiler → easy_prof}/profile_instance.rb +41 -18
- data/lib/{easy_profiler → easy_prof}/profile_instance_base.rb +14 -6
- data/lib/easy_prof/version.rb +4 -0
- data/spec/profile_instance_spec.rb +20 -11
- data/spec/profile_spec.rb +18 -6
- data/spec/spec_helper.rb +2 -2
- metadata +103 -26
- data/README.rdoc +0 -248
- data/VERSION.yml +0 -5
- data/init.rb +0 -1
data/.gitignore
CHANGED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,239 @@
|
|
1
|
+
# easy-prof
|
2
|
+
|
3
|
+
[](http://travis-ci.org/kpumuk/easy-prof)
|
4
|
+
|
5
|
+
Simple and easy to use Ruby code profiler, which could be used
|
6
|
+
as a Rails plugin.
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
Add the "easy-prof" gem to your `Gemfile`.
|
11
|
+
|
12
|
+
gem "easy-prof"
|
13
|
+
|
14
|
+
And run `bundle install` command.
|
15
|
+
|
16
|
+
## Description
|
17
|
+
|
18
|
+
The main idea behind the easy-prof is creating check points and your
|
19
|
+
code and measuring time needed to execute code blocks. Here is the
|
20
|
+
example of easy-prof output:
|
21
|
+
|
22
|
+
[home#index] Benchmark results:
|
23
|
+
[home#index] debug: Logged in user home page
|
24
|
+
[home#index] progress: 0.7002 s [find top videos]
|
25
|
+
[home#index] progress: 0.0452 s [build categories list]
|
26
|
+
[home#index] progress: 0.0019 s [build tag cloud]
|
27
|
+
[home#index] progress: 0.0032 s [find featured videos]
|
28
|
+
[home#index] progress: 0.0324 s [find latest videos]
|
29
|
+
[home#index] debug: VIEW STARTED
|
30
|
+
[home#index] progress: 0.0649 s [top videos render]
|
31
|
+
[home#index] progress: 0.0014 s [categories render]
|
32
|
+
[home#index] progress: 2.5887 s [tag cloud render]
|
33
|
+
[home#index] progress: 0.0488 s [latest videos render]
|
34
|
+
[home#index] progress: 0.1053 s [featured video render]
|
35
|
+
[home#index] results: 3.592 s
|
36
|
+
|
37
|
+
From this output you can see what checkpoints takes longer to reach,
|
38
|
+
and what code fragments are pretty fast.
|
39
|
+
|
40
|
+
## Usage
|
41
|
+
|
42
|
+
The library extends `Kernel` with a method `easy_profiler`.
|
43
|
+
By default profiling is disabled globally, so you should pass `:enabled`
|
44
|
+
parameter to enable profiling of particular code. Also there is a time
|
45
|
+
`:limit` option which could be used to skip logging of blocks which are
|
46
|
+
fast enough.
|
47
|
+
|
48
|
+
For more details see the options description below.
|
49
|
+
|
50
|
+
easy_profiler('sleep', :enabled => true) do |p|
|
51
|
+
sleep 1
|
52
|
+
p.progress('sleep 1')
|
53
|
+
p.debug('checkpoint reached')
|
54
|
+
sleep 2
|
55
|
+
p.progress('sleep 2')
|
56
|
+
end
|
57
|
+
|
58
|
+
Method accepts two parameters: profiling session name and a hash of
|
59
|
+
options:
|
60
|
+
|
61
|
+
* `:enabled` — value indicating whether profiling is enabled.
|
62
|
+
* `:limit` — minimum time period which should be reached to
|
63
|
+
print profiling log.
|
64
|
+
* `:count_ar_instances` — indicating whether profiler should
|
65
|
+
log an approximate number of instantiated ActiveRecord objects.
|
66
|
+
* `:count_memory_usage` — indicating whether profiler should
|
67
|
+
log an approximate amount of memory used.
|
68
|
+
* `:logger` — a `Logger` instance.
|
69
|
+
|
70
|
+
## Configuration
|
71
|
+
|
72
|
+
There are some global configuration options exists:
|
73
|
+
|
74
|
+
EasyProfiler.configure do |config|
|
75
|
+
config.enable_profiling = false
|
76
|
+
config.print_limit = 0.01
|
77
|
+
config.count_ar_instances = false
|
78
|
+
config.count_memory_usage = false
|
79
|
+
config.logger = nil # or Rails.logger or whatever
|
80
|
+
config.colorize_logging = true
|
81
|
+
config.live_logging = false
|
82
|
+
end
|
83
|
+
|
84
|
+
* `enable_profiling` — used to enable or disable profiling
|
85
|
+
globalle (`false` by default).
|
86
|
+
* `print_limit` — used to set a minimum time period in seconds
|
87
|
+
which should be reached to dump profile to the log (`0.01`
|
88
|
+
by default).
|
89
|
+
* `count_ar_instances` — indicating whether profiler should
|
90
|
+
log an approximate number of instantiated ActiveRecord objects.
|
91
|
+
* `count_memory_usage` — indicating whether profiler should
|
92
|
+
log an approximate amount of memory used.
|
93
|
+
* `logger` — a `Logger` instance to dump logs to.
|
94
|
+
* `colorize_logging` — when `true`, output will be
|
95
|
+
colorized (useful when dumping profiling information into the
|
96
|
+
Rails log).
|
97
|
+
* `live_logging` — when `true`, every profiling info
|
98
|
+
will be pushed to the log immediately (by default everything will
|
99
|
+
be dumped in the end of profiling session).
|
100
|
+
|
101
|
+
## Active Record instances number profiling
|
102
|
+
|
103
|
+
easy-prof can log a number of instantiated ActiveRecord instances.
|
104
|
+
To enable this kind of profiling, use a `:count_ar_instances`
|
105
|
+
option or global setting with the same name.
|
106
|
+
|
107
|
+
Please note, that easy-prof completely disables garbage collector
|
108
|
+
during this kind of profiling. It could hurt your overall application
|
109
|
+
performance, so do not use it on production boxes. Also I can't
|
110
|
+
guaranty 100% precision, but it is about this value in almost all
|
111
|
+
cases.
|
112
|
+
|
113
|
+
Further reading:
|
114
|
+
* [That’s Not a Memory Leak, It’s Bloat](http://www.engineyard.com/blog/2009/thats-not-a-memory-leak-its-bloat)
|
115
|
+
|
116
|
+
## Memory usage profiling
|
117
|
+
|
118
|
+
The plugin is able to log an amount of memory used by current Ruby
|
119
|
+
process. To enable this kind of profiling, use a `:count_memory_usage`
|
120
|
+
option or global setting with the same name.
|
121
|
+
|
122
|
+
Please note, that easy-prof completely disables garbage collector
|
123
|
+
during this kind of profiling. It could hurt your overall application
|
124
|
+
performance, so do not use it on production boxes. Also I can't
|
125
|
+
guaranty 100% precision, but it is about this value in almost all
|
126
|
+
cases.
|
127
|
+
|
128
|
+
## Dumping results to the Firebug console
|
129
|
+
|
130
|
+
If you are profiling a Ruby on Rails application, it could be useful
|
131
|
+
to get profiling results from production server sometimes. To achieve
|
132
|
+
this you can use a `FirebugLogger`, bundled with this plugin.
|
133
|
+
In any controller you have a helper called `firebug_logger`,
|
134
|
+
so you can pass it to EasyProfiler using `:logger` option:
|
135
|
+
|
136
|
+
easy_profiler('home#index', :logger => firebug_logger, :limit => 2) do |p|
|
137
|
+
end
|
138
|
+
|
139
|
+
The idea behind this logger is pretty simple (as everything in this
|
140
|
+
plugin): there is an `after_filter` named `dump_firebug_profile`,
|
141
|
+
which dumps profiling information after your action finished its work.
|
142
|
+
Please note: it will not output any line when profiling session is
|
143
|
+
disabled or time limit is not reached.
|
144
|
+
|
145
|
+
Do not forget to protect firebug output: it is a bad idea to allow
|
146
|
+
anyone to see your profiling session dump. You can allow admin
|
147
|
+
users only to use firebug, or restrict this feature by IP address.
|
148
|
+
|
149
|
+
BTW, you can use Firebug Console Lite (http://getfirebug.com/lite.html)
|
150
|
+
to get this feature working in any browser! By default it works
|
151
|
+
perfectly in Firefox with Firebug installed, and in Safari 4.
|
152
|
+
|
153
|
+
## Ruby on Rails application profiling
|
154
|
+
|
155
|
+
Here is a complete example of a Rails action profiling:
|
156
|
+
|
157
|
+
class HomeController < ApplicationController
|
158
|
+
def index
|
159
|
+
easy_profiler('home#index', :enabled => profile_request?, :limit => 2) do |p|
|
160
|
+
p.progress 'logged in user home page'
|
161
|
+
|
162
|
+
@top_videos = Video.top(:limit => 10)
|
163
|
+
p.progress 'find top videos'
|
164
|
+
|
165
|
+
@categories = Category.all(:order => 'name DESC')
|
166
|
+
p.progress 'build categories list'
|
167
|
+
|
168
|
+
@tag_cloud = Tag.tag_cloud(:limit => 200)
|
169
|
+
p.progress 'build tag cloud'
|
170
|
+
|
171
|
+
@featured_videos = Video.featured(limit => 5)
|
172
|
+
p.progress 'find featured videos'
|
173
|
+
|
174
|
+
@latest_videos = Video.latest(:limit => 5)
|
175
|
+
p.progress 'find latest videos'
|
176
|
+
|
177
|
+
@profiler = p
|
178
|
+
p.debug 'VIEW STARTED'
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
private
|
183
|
+
|
184
|
+
# Method returns +true+ if current request should ouput profiling information
|
185
|
+
def profile_request?
|
186
|
+
params['_with_profiling'] == 'yes'
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
And a view:
|
191
|
+
|
192
|
+
<div id="top_videos">
|
193
|
+
<%= render :partial => 'top_videos' %>
|
194
|
+
<% @profiler.progress 'top videos render' %>
|
195
|
+
</div>
|
196
|
+
|
197
|
+
<div class="tabs">
|
198
|
+
<ul id="taxonomy">
|
199
|
+
<li><a href="#" id="categories" class="current">Categories</a></li>
|
200
|
+
<li><a href="#" id="tags">Tags</a></li>
|
201
|
+
</ul>
|
202
|
+
<div class="categories_panel">
|
203
|
+
<%= render :partial => 'categories' %>
|
204
|
+
<% @profiler.progress 'categories render' %>
|
205
|
+
</div>
|
206
|
+
<div class="categories_panel hidden">
|
207
|
+
<%= render :partial => 'tag_cloud' %>
|
208
|
+
<% @profiler.progress 'tag cloud render' %>
|
209
|
+
</div>
|
210
|
+
</div>
|
211
|
+
|
212
|
+
<div class="box">
|
213
|
+
<div id="latest">
|
214
|
+
<%= render :partial => 'videos', :videos => @latest_videos %>
|
215
|
+
<% @profiler.progress 'latest videos render' %>
|
216
|
+
</div>
|
217
|
+
<div id="featured">
|
218
|
+
<%= render :partial => 'videos', :videos => @featured_videos %>
|
219
|
+
<% @profiler.progress 'featured video render' %>
|
220
|
+
</div>
|
221
|
+
</div>
|
222
|
+
|
223
|
+
As you can see from this example, profiler will be enabled only when
|
224
|
+
you pass a _with_profiling parameter with value yes:
|
225
|
+
|
226
|
+
http://example.com/home?_with_profiling=yes
|
227
|
+
|
228
|
+
## Who are the authors?
|
229
|
+
|
230
|
+
This plugin has been created in Scribd.com for our internal use
|
231
|
+
and then the sources were opened for other people to use. All the
|
232
|
+
code in this package has been developed by Dmytro Shteflyuk for
|
233
|
+
Scribd.com and is released under the MIT license. For more details,
|
234
|
+
see the MIT-LICENSE file.
|
235
|
+
|
236
|
+
## Credits
|
237
|
+
|
238
|
+
* Dmytro Shteflyuk (author) <kpumuk@kpumuk.info> http://kpumuk.info
|
239
|
+
* Alexey Kovyrin (contributor) <alexey@kovyrin.net> http://kovyrin.net
|
data/Rakefile
CHANGED
@@ -1,36 +1,11 @@
|
|
1
|
-
require '
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
2
3
|
|
3
|
-
|
4
|
-
|
5
|
-
Jeweler::Tasks.new do |gemspec|
|
6
|
-
gemspec.name = 'easy-prof'
|
7
|
-
gemspec.summary = 'Simple and easy to use Ruby code profiler'
|
8
|
-
gemspec.description = 'Simple Ruby code profiler to use both in Rails applications and generic Ruby scripts.'
|
9
|
-
gemspec.email = 'kpumuk@kpumuk.info'
|
10
|
-
gemspec.homepage = 'http://github.com/kpumuk/easy-prof'
|
11
|
-
gemspec.authors = ['Dmytro Shteflyuk']
|
12
|
-
end
|
13
|
-
Jeweler::GemcutterTasks.new
|
14
|
-
rescue LoadError
|
15
|
-
puts 'Jeweler not available. Install it with: sudo gem install jeweler'
|
16
|
-
end
|
17
|
-
|
18
|
-
begin
|
19
|
-
require 'spec/rake/spectask'
|
20
|
-
|
21
|
-
desc 'Default: run unit tests.'
|
22
|
-
task :default => :spec
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
RSpec::Core::RakeTask.new(:spec)
|
23
6
|
|
24
|
-
|
25
|
-
|
26
|
-
t.libs << 'lib'
|
27
|
-
t.pattern = 'spec/**/*_spec.rb'
|
28
|
-
t.verbose = true
|
29
|
-
t.spec_opts = ['-cfs']
|
30
|
-
end
|
31
|
-
rescue LoadError
|
32
|
-
puts 'RSpec not available. Install it with: sudo gem install rspec'
|
33
|
-
end
|
7
|
+
task :test => :spec
|
8
|
+
task :default => :spec
|
34
9
|
|
35
10
|
begin
|
36
11
|
require 'yard'
|
data/easy-prof.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path('../lib', __FILE__)
|
3
|
+
require 'easy_prof/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'easy-prof'
|
7
|
+
s.version = EasyProfiler::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ['Dmytro Shteflyuk']
|
10
|
+
s.email = ['kpumuk@kpumuk.info']
|
11
|
+
s.homepage = 'http://github.com/kpumuk/easy-prof'
|
12
|
+
s.summary = %q{Simple and easy to use Ruby code profiler.}
|
13
|
+
s.description = %q{Simple Ruby code profiler to use both in Rails applications and generic Ruby scripts.}
|
14
|
+
|
15
|
+
s.add_development_dependency 'activerecord', '~> 3.2.15'
|
16
|
+
s.add_development_dependency 'rake'
|
17
|
+
s.add_development_dependency 'rspec'
|
18
|
+
s.add_development_dependency 'yard'
|
19
|
+
s.add_development_dependency 'bluecloth'
|
20
|
+
|
21
|
+
s.files = `git ls-files`.split("\n")
|
22
|
+
s.test_files = `git ls-files -- {spec}/*`.split("\n")
|
23
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
24
|
+
s.extra_rdoc_files = ['README.md']
|
25
|
+
s.rdoc_options = ['--charset=UTF-8']
|
26
|
+
s.require_paths = ['lib']
|
27
|
+
end
|
data/lib/easy-prof.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'easy_prof'
|
data/lib/easy_prof.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
require 'logger'
|
2
2
|
|
3
3
|
module EasyProfiler
|
4
|
-
autoload :Configuration, '
|
5
|
-
autoload :Profile, '
|
6
|
-
autoload :ProfileInstanceBase, '
|
7
|
-
autoload :ProfileInstance, '
|
8
|
-
autoload :NoProfileInstance, '
|
9
|
-
autoload :FirebugLogger, '
|
10
|
-
autoload :ActionControllerExtensions, '
|
4
|
+
autoload :Configuration, 'easy_prof/configuration'
|
5
|
+
autoload :Profile, 'easy_prof/profile'
|
6
|
+
autoload :ProfileInstanceBase, 'easy_prof/profile_instance_base'
|
7
|
+
autoload :ProfileInstance, 'easy_prof/profile_instance'
|
8
|
+
autoload :NoProfileInstance, 'easy_prof/no_profile_instance'
|
9
|
+
autoload :FirebugLogger, 'easy_prof/firebug_logger'
|
10
|
+
autoload :ActionControllerExtensions, 'easy_prof/action_controller_extensions'
|
11
11
|
|
12
12
|
module ClassMethods
|
13
13
|
def configure(force = false)
|
File without changes
|
@@ -2,7 +2,7 @@ module EasyProfiler
|
|
2
2
|
class Configuration
|
3
3
|
# Value indicating whether profiling is globally enabled.
|
4
4
|
attr_reader :enable_profiling
|
5
|
-
|
5
|
+
|
6
6
|
# Minimum time period which should be reached to dump
|
7
7
|
# profile to the log.
|
8
8
|
attr_reader :print_limit
|
@@ -32,10 +32,10 @@ module EasyProfiler
|
|
32
32
|
@count_ar_instances = false
|
33
33
|
@count_memory_usage = false
|
34
34
|
@logger = nil
|
35
|
-
@colorize_logging =
|
35
|
+
@colorize_logging = false
|
36
36
|
@live_logging = false
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
# Sets a value indicating whether profiling is globally enabled.
|
40
40
|
def enable_profiling=(value)
|
41
41
|
@enable_profiling = !!value
|
@@ -55,10 +55,10 @@ module EasyProfiler
|
|
55
55
|
|
56
56
|
# Sets a value indicating whether profiler should log an
|
57
57
|
# approximate amount of memory used.
|
58
|
-
#
|
58
|
+
#
|
59
59
|
# @param Boolean value
|
60
60
|
# identifies whether memory profiling should be enabled.
|
61
|
-
#
|
61
|
+
#
|
62
62
|
def count_memory_usage=(value)
|
63
63
|
@count_memory_usage = !!value
|
64
64
|
end
|
@@ -69,7 +69,7 @@ module EasyProfiler
|
|
69
69
|
|
70
70
|
# Sets a value indicating whether profiler should flush
|
71
71
|
# logs on every checkpoint.
|
72
|
-
#
|
72
|
+
#
|
73
73
|
def live_logging=(value)
|
74
74
|
@live_logging = !!value
|
75
75
|
end
|
@@ -82,7 +82,7 @@ module EasyProfiler
|
|
82
82
|
# information directly to STDOUT. You can use
|
83
83
|
# <tt>EasyProfiler.configuration.logger</tt> to set another
|
84
84
|
# logger.
|
85
|
-
#
|
85
|
+
#
|
86
86
|
def logger
|
87
87
|
unless @logger
|
88
88
|
@logger = if Object.const_defined?(:Rails)
|
@@ -105,16 +105,26 @@ module EasyProfiler
|
|
105
105
|
config.logger = options[:logger] if options.has_key?(:logger)
|
106
106
|
config.colorize_logging = options[:colorize_logging] if options.has_key?(:colorize_logging)
|
107
107
|
config.live_logging = options[:live_logging] if options.has_key?(:live_logging)
|
108
|
-
|
109
108
|
config
|
110
109
|
end
|
111
|
-
|
110
|
+
|
111
|
+
def self.parse(config)
|
112
|
+
case config
|
113
|
+
when Hash
|
114
|
+
EasyProfiler.configuration.merge(config)
|
115
|
+
when EasyProfiler::Configuration
|
116
|
+
config
|
117
|
+
else
|
118
|
+
EasyProfiler.configuration
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
112
122
|
def disable_gc?
|
113
123
|
count_ar_instances or count_memory_usage
|
114
124
|
end
|
115
|
-
|
125
|
+
|
116
126
|
def enabled?
|
117
127
|
enable_profiling
|
118
128
|
end
|
119
129
|
end
|
120
|
-
end
|
130
|
+
end
|
File without changes
|
File without changes
|
@@ -21,20 +21,22 @@ module EasyProfiler
|
|
21
21
|
#
|
22
22
|
# Returns:
|
23
23
|
# * an instance of profiler (descendant of the <tt>EasyProfiler::ProfileInstanceBase</tt> class).
|
24
|
-
def self.start(name,
|
24
|
+
def self.start(name, config = nil)
|
25
25
|
if @@profile_results[name]
|
26
26
|
raise ArgumentError.new("EasyProfiler::Profile.start() collision! '#{name}' is already started.")
|
27
27
|
end
|
28
28
|
|
29
|
-
config =
|
30
|
-
|
31
|
-
# Disable garbage collector to get more precise results
|
32
|
-
GC.disable if config.disable_gc?
|
29
|
+
config = Configuration.parse(config)
|
33
30
|
|
34
31
|
klass = config.enabled? ? ProfileInstance : NoProfileInstance
|
35
32
|
instance = klass.new(name, config)
|
36
33
|
|
37
34
|
@@profile_results[name] = instance
|
35
|
+
|
36
|
+
# Disable garbage collector to get more precise results
|
37
|
+
GC.disable if instance.config.disable_gc?
|
38
|
+
|
39
|
+
instance
|
38
40
|
end
|
39
41
|
|
40
42
|
# Finishes a profiling session and dumps results to the log.
|
@@ -53,7 +55,7 @@ module EasyProfiler
|
|
53
55
|
end
|
54
56
|
|
55
57
|
def self.reset!
|
56
|
-
@@profile_results
|
58
|
+
@@profile_results = {}
|
57
59
|
end
|
58
60
|
end
|
59
|
-
end
|
61
|
+
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
module EasyProfiler
|
2
2
|
# Class used when profiling is disabled.
|
3
3
|
class ProfileInstance < ProfileInstanceBase
|
4
|
+
@@groups_stack = []
|
5
|
+
|
4
6
|
# Sets a profiling checkpoint (block execution time will be printed).
|
5
7
|
#
|
6
8
|
# Parameters:
|
@@ -33,15 +35,32 @@ module EasyProfiler
|
|
33
35
|
buffer_checkpoint("debug: #{message}")
|
34
36
|
end
|
35
37
|
|
38
|
+
# Start a group with a specified name.
|
39
|
+
#
|
40
|
+
# Parameters:
|
41
|
+
# * name -- a name of the group.
|
42
|
+
#
|
43
|
+
def group(name)
|
44
|
+
progress "Before group '#{name}'"
|
45
|
+
debug 'Started group'
|
46
|
+
@@groups_stack << name
|
47
|
+
end
|
48
|
+
|
49
|
+
def end_group
|
50
|
+
debug "Finished group"
|
51
|
+
@@groups_stack.pop
|
52
|
+
end
|
53
|
+
|
36
54
|
# Dumps results to the log.
|
37
55
|
def dump_results
|
56
|
+
self.end_group while @@groups_stack.any?
|
57
|
+
|
38
58
|
progress('END')
|
39
|
-
t = total
|
40
59
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
60
|
+
t = total
|
61
|
+
log_footer(t)
|
62
|
+
if false === config.print_limit || t > config.print_limit.to_f
|
63
|
+
@buffer.each { |message| log_line(*message) }
|
45
64
|
end
|
46
65
|
end
|
47
66
|
|
@@ -64,20 +83,22 @@ module EasyProfiler
|
|
64
83
|
|
65
84
|
# Buffers a profiling checkpoint.
|
66
85
|
def buffer_checkpoint(message)
|
67
|
-
log_header
|
86
|
+
log_header unless @header_printed
|
87
|
+
|
88
|
+
group_name = @@groups_stack.last
|
89
|
+
name = group_name ? "#{@name}: #{group_name}" : @name
|
90
|
+
|
68
91
|
if config.live_logging
|
69
|
-
log_line(message)
|
92
|
+
log_line(message, name)
|
70
93
|
else
|
71
|
-
@buffer << message
|
94
|
+
@buffer << [message, name]
|
72
95
|
end
|
73
96
|
end
|
74
97
|
|
75
98
|
# Write a header to the log.
|
76
|
-
def log_header
|
77
|
-
|
78
|
-
|
79
|
-
@header_printed = true
|
80
|
-
end
|
99
|
+
def log_header
|
100
|
+
@header_printed = true
|
101
|
+
buffer_checkpoint("Benchmark results:")
|
81
102
|
end
|
82
103
|
|
83
104
|
# Write a footer with summary stats to the log.
|
@@ -90,11 +111,13 @@ module EasyProfiler
|
|
90
111
|
", #{format_memory_size(total_memory_usage)}"
|
91
112
|
end
|
92
113
|
|
93
|
-
|
114
|
+
buffer_checkpoint("results: %0.4f s#{ar_instances_count}#{memory_usage_value}" % total_time)
|
94
115
|
end
|
95
116
|
|
96
117
|
# Write a log line.
|
97
|
-
def log_line(line)
|
118
|
+
def log_line(line, name = nil)
|
119
|
+
name ||= @name
|
120
|
+
|
98
121
|
if config.colorize_logging
|
99
122
|
@@row_even, message_color = if @@row_even
|
100
123
|
[false, '4;32;1']
|
@@ -102,10 +125,10 @@ module EasyProfiler
|
|
102
125
|
[true, '4;33;1']
|
103
126
|
end
|
104
127
|
|
105
|
-
config.logger.info("
|
128
|
+
config.logger.info("[\e[#{message_color}m%s\e[0m] %s" % [name, line])
|
106
129
|
else
|
107
|
-
config.logger.info("[%s] %s" % [
|
130
|
+
config.logger.info("[%s] %s" % [name, line])
|
108
131
|
end
|
109
132
|
end
|
110
133
|
end
|
111
|
-
end
|
134
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module EasyProfiler
|
2
2
|
# Base class for profilers.
|
3
3
|
class ProfileInstanceBase
|
4
|
-
attr_reader :name, :config
|
4
|
+
attr_reader :name, :config, :buffer
|
5
5
|
|
6
6
|
@@row_even = true
|
7
7
|
|
@@ -12,11 +12,7 @@ module EasyProfiler
|
|
12
12
|
# * options -- a +Hash+ of options (see <tt>EasyProfiler::Profile.start</tt> for details).
|
13
13
|
def initialize(name, config = nil)
|
14
14
|
@name = name
|
15
|
-
@config =
|
16
|
-
when Hash: EasyProfiler.configuration.merge(config)
|
17
|
-
when EasyProfiler::Configuration: config
|
18
|
-
else EasyProfiler.configuration
|
19
|
-
end
|
15
|
+
@config = Configuration.parse(config)
|
20
16
|
|
21
17
|
@start = @progress = Time.now.to_f
|
22
18
|
|
@@ -52,6 +48,18 @@ module EasyProfiler
|
|
52
48
|
def debug(message)
|
53
49
|
end
|
54
50
|
|
51
|
+
# Start a group with a specified name.
|
52
|
+
#
|
53
|
+
# Parameters:
|
54
|
+
# * name -- a name of the group.
|
55
|
+
#
|
56
|
+
def group(name, options = {}, &block)
|
57
|
+
self
|
58
|
+
end
|
59
|
+
|
60
|
+
def end_group
|
61
|
+
end
|
62
|
+
|
55
63
|
# Dumps results to the log.
|
56
64
|
def dump_results
|
57
65
|
end
|
@@ -6,7 +6,7 @@ describe EasyProfiler::ProfileInstance do
|
|
6
6
|
profiler.name.should == 'myprofiler1'
|
7
7
|
profiler.config.should be(EasyProfiler.configuration)
|
8
8
|
|
9
|
-
profiler = EasyProfiler::ProfileInstance.new('myprofiler2',
|
9
|
+
profiler = EasyProfiler::ProfileInstance.new('myprofiler2', :print_limit => 100)
|
10
10
|
profiler.name.should == 'myprofiler2'
|
11
11
|
profiler.config.print_limit.should == 100
|
12
12
|
|
@@ -17,14 +17,23 @@ describe EasyProfiler::ProfileInstance do
|
|
17
17
|
profiler.config.should be(config)
|
18
18
|
end
|
19
19
|
|
20
|
+
it 'should not change global configuration options' do
|
21
|
+
EasyProfiler.config.print_limit = 10
|
22
|
+
|
23
|
+
profiler = EasyProfiler::ProfileInstance.new('myprofiler1', :print_limit => 100)
|
24
|
+
profiler.config.print_limit.should == 100
|
25
|
+
|
26
|
+
EasyProfiler.config.print_limit.should == 10
|
27
|
+
end
|
28
|
+
|
20
29
|
it 'should respond to :progress' do
|
21
30
|
profiler = EasyProfiler::ProfileInstance.new('myprofiler')
|
22
31
|
profiler.should respond_to(:progress)
|
23
32
|
lambda {
|
24
33
|
profiler.progress('message')
|
25
|
-
buffer
|
26
|
-
buffer.should
|
27
|
-
buffer.
|
34
|
+
profiler.buffer.should have(2).items
|
35
|
+
profiler.buffer[1][0].should match(/progress: \d+\.\d+ s \[message\]/)
|
36
|
+
profiler.buffer[1][1].should == 'myprofiler'
|
28
37
|
}.should_not raise_error
|
29
38
|
end
|
30
39
|
|
@@ -33,14 +42,14 @@ describe EasyProfiler::ProfileInstance do
|
|
33
42
|
profiler.should respond_to(:debug)
|
34
43
|
lambda {
|
35
44
|
profiler.debug('message')
|
36
|
-
buffer
|
37
|
-
buffer.should
|
38
|
-
buffer.
|
45
|
+
profiler.buffer.should have(2).item
|
46
|
+
profiler.buffer[1][0].should match(/debug: message/)
|
47
|
+
profiler.buffer[1][1].should == 'myprofiler'
|
39
48
|
}.should_not raise_error
|
40
49
|
end
|
41
50
|
|
42
51
|
it 'should respond to :dump_results' do
|
43
|
-
logger =
|
52
|
+
logger = double('MockLogger')
|
44
53
|
profiler = EasyProfiler::ProfileInstance.new('myprofiler', :logger => logger, :enabled => true, :limit => false, :colorize_logging => false)
|
45
54
|
profiler.should respond_to(:dump_results)
|
46
55
|
|
@@ -57,7 +66,7 @@ describe EasyProfiler::ProfileInstance do
|
|
57
66
|
end
|
58
67
|
|
59
68
|
it 'should render nothing when time limit not reached' do
|
60
|
-
logger =
|
69
|
+
logger = double('MockLogger')
|
61
70
|
profiler = EasyProfiler::ProfileInstance.new('myprofiler', :logger => logger, :enabled => true, :limit => 20)
|
62
71
|
logger.should_not_receive(:info)
|
63
72
|
profiler.dump_results
|
@@ -65,7 +74,7 @@ describe EasyProfiler::ProfileInstance do
|
|
65
74
|
|
66
75
|
context 'when live logging is enabled' do
|
67
76
|
before :each do
|
68
|
-
@logger =
|
77
|
+
@logger = double('MockLogger').as_null_object
|
69
78
|
@profiler = EasyProfiler::ProfileInstance.new('myprofiler', :logger => @logger, :enabled => true, :live_logging => true, :colorize_logging => false)
|
70
79
|
end
|
71
80
|
|
@@ -110,4 +119,4 @@ describe EasyProfiler::ProfileInstance do
|
|
110
119
|
@profiler.dump_results
|
111
120
|
end
|
112
121
|
end
|
113
|
-
end
|
122
|
+
end
|
data/spec/profile_spec.rb
CHANGED
@@ -7,10 +7,13 @@ describe EasyProfiler::Profile do
|
|
7
7
|
config.print_limit = 0.01
|
8
8
|
config.count_ar_instances = false
|
9
9
|
config.count_memory_usage = false
|
10
|
+
config.logger = nil
|
11
|
+
config.colorize_logging = false
|
12
|
+
config.live_logging = false
|
10
13
|
end
|
11
14
|
EasyProfiler::Profile.reset!
|
12
15
|
end
|
13
|
-
|
16
|
+
|
14
17
|
context '.start' do
|
15
18
|
it 'should pass name to profile instance' do
|
16
19
|
EasyProfiler::Profile.start('myprofiler').name.should == 'myprofiler'
|
@@ -21,6 +24,15 @@ describe EasyProfiler::Profile do
|
|
21
24
|
EasyProfiler::Profile.start('myprofiler', options).config.print_limit.should == 100
|
22
25
|
end
|
23
26
|
|
27
|
+
it 'should not change global configuration options' do
|
28
|
+
EasyProfiler.config.print_limit = 10
|
29
|
+
|
30
|
+
profiler = EasyProfiler::Profile.start('myprofiler', :print_limit => 100)
|
31
|
+
profiler.config.print_limit.should == 100
|
32
|
+
|
33
|
+
EasyProfiler.config.print_limit.should == 10
|
34
|
+
end
|
35
|
+
|
24
36
|
it 'should create a ProfileInstance object when enabled' do
|
25
37
|
options = { :enabled => true }
|
26
38
|
EasyProfiler::Profile.start('myprofiler', options).class.should == EasyProfiler::ProfileInstance
|
@@ -63,7 +75,7 @@ describe EasyProfiler::Profile do
|
|
63
75
|
end
|
64
76
|
|
65
77
|
it 'should use global :logger value' do
|
66
|
-
logger =
|
78
|
+
logger = double('MockLogger')
|
67
79
|
EasyProfiler.config.logger = logger
|
68
80
|
EasyProfiler::Profile.start('myprofiler2').config.logger.should be(logger)
|
69
81
|
end
|
@@ -73,7 +85,7 @@ describe EasyProfiler::Profile do
|
|
73
85
|
EasyProfiler.config.live_logging = true
|
74
86
|
EasyProfiler::Profile.start('myprofiler2').config.live_logging.should be_true
|
75
87
|
end
|
76
|
-
|
88
|
+
|
77
89
|
it 'should disable garbage collector when needed' do
|
78
90
|
options = { :enabled => true, :count_ar_instances => true }
|
79
91
|
GC.should_receive(:disable)
|
@@ -100,14 +112,14 @@ describe EasyProfiler::Profile do
|
|
100
112
|
|
101
113
|
it 'should enable back garbage collector when needed' do
|
102
114
|
profiler = mock_profile_start('myprofiler1', :enabled => true, :count_ar_instances => true)
|
103
|
-
profiler.stub
|
115
|
+
profiler.stub(:dump_results)
|
104
116
|
GC.should_receive(:enable)
|
105
117
|
EasyProfiler::Profile.stop('myprofiler1')
|
106
118
|
|
107
119
|
profiler = mock_profile_start('myprofiler2', :enabled => true, :count_memory_usage => true)
|
108
|
-
profiler.stub
|
120
|
+
profiler.stub(:dump_results)
|
109
121
|
GC.should_receive(:enable)
|
110
122
|
EasyProfiler::Profile.stop('myprofiler2')
|
111
123
|
end
|
112
124
|
end
|
113
|
-
end
|
125
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -4,6 +4,6 @@ require File.join(File.dirname(__FILE__), "../lib/easy_prof")
|
|
4
4
|
|
5
5
|
def mock_profile_start(name, options = {})
|
6
6
|
config = EasyProfiler.configuration.merge(options)
|
7
|
-
profiler =
|
7
|
+
profiler = double('MockProfiler', :name => name, :config => config)
|
8
8
|
EasyProfiler::Profile.send(:class_variable_get, :@@profile_results)[name] = profiler
|
9
|
-
end
|
9
|
+
end
|
metadata
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: easy-prof
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 19
|
5
|
+
prerelease:
|
5
6
|
segments:
|
6
7
|
- 1
|
8
|
+
- 1
|
7
9
|
- 0
|
8
|
-
|
9
|
-
version: 1.0.0
|
10
|
+
version: 1.1.0
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- Dmytro Shteflyuk
|
@@ -14,33 +15,109 @@ autorequire:
|
|
14
15
|
bindir: bin
|
15
16
|
cert_chain: []
|
16
17
|
|
17
|
-
date:
|
18
|
+
date: 2013-11-13 00:00:00 -05:00
|
18
19
|
default_executable:
|
19
|
-
dependencies:
|
20
|
-
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: activerecord
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 17
|
30
|
+
segments:
|
31
|
+
- 3
|
32
|
+
- 2
|
33
|
+
- 15
|
34
|
+
version: 3.2.15
|
35
|
+
type: :development
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: rake
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 3
|
46
|
+
segments:
|
47
|
+
- 0
|
48
|
+
version: "0"
|
49
|
+
type: :development
|
50
|
+
version_requirements: *id002
|
51
|
+
- !ruby/object:Gem::Dependency
|
52
|
+
name: rspec
|
53
|
+
prerelease: false
|
54
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
hash: 3
|
60
|
+
segments:
|
61
|
+
- 0
|
62
|
+
version: "0"
|
63
|
+
type: :development
|
64
|
+
version_requirements: *id003
|
65
|
+
- !ruby/object:Gem::Dependency
|
66
|
+
name: yard
|
67
|
+
prerelease: false
|
68
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
hash: 3
|
74
|
+
segments:
|
75
|
+
- 0
|
76
|
+
version: "0"
|
77
|
+
type: :development
|
78
|
+
version_requirements: *id004
|
79
|
+
- !ruby/object:Gem::Dependency
|
80
|
+
name: bluecloth
|
81
|
+
prerelease: false
|
82
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
hash: 3
|
88
|
+
segments:
|
89
|
+
- 0
|
90
|
+
version: "0"
|
91
|
+
type: :development
|
92
|
+
version_requirements: *id005
|
21
93
|
description: Simple Ruby code profiler to use both in Rails applications and generic Ruby scripts.
|
22
|
-
email:
|
94
|
+
email:
|
95
|
+
- kpumuk@kpumuk.info
|
23
96
|
executables: []
|
24
97
|
|
25
98
|
extensions: []
|
26
99
|
|
27
100
|
extra_rdoc_files:
|
28
|
-
- README.
|
101
|
+
- README.md
|
29
102
|
files:
|
30
103
|
- .gitignore
|
104
|
+
- .travis.yml
|
105
|
+
- Gemfile
|
106
|
+
- Gemfile.lock
|
31
107
|
- MIT-LICENSE
|
32
|
-
- README.
|
108
|
+
- README.md
|
33
109
|
- Rakefile
|
34
|
-
-
|
35
|
-
-
|
110
|
+
- easy-prof.gemspec
|
111
|
+
- lib/easy-prof.rb
|
36
112
|
- lib/easy_prof.rb
|
37
|
-
- lib/
|
38
|
-
- lib/
|
39
|
-
- lib/
|
40
|
-
- lib/
|
41
|
-
- lib/
|
42
|
-
- lib/
|
43
|
-
- lib/
|
113
|
+
- lib/easy_prof/action_controller_extensions.rb
|
114
|
+
- lib/easy_prof/configuration.rb
|
115
|
+
- lib/easy_prof/firebug_logger.rb
|
116
|
+
- lib/easy_prof/no_profile_instance.rb
|
117
|
+
- lib/easy_prof/profile.rb
|
118
|
+
- lib/easy_prof/profile_instance.rb
|
119
|
+
- lib/easy_prof/profile_instance_base.rb
|
120
|
+
- lib/easy_prof/version.rb
|
44
121
|
- spec/easy_profiler_spec.rb
|
45
122
|
- spec/no_profile_instance_spec.rb
|
46
123
|
- spec/profile_instance_spec.rb
|
@@ -56,29 +133,29 @@ rdoc_options:
|
|
56
133
|
require_paths:
|
57
134
|
- lib
|
58
135
|
required_ruby_version: !ruby/object:Gem::Requirement
|
136
|
+
none: false
|
59
137
|
requirements:
|
60
138
|
- - ">="
|
61
139
|
- !ruby/object:Gem::Version
|
140
|
+
hash: 3
|
62
141
|
segments:
|
63
142
|
- 0
|
64
143
|
version: "0"
|
65
144
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
145
|
+
none: false
|
66
146
|
requirements:
|
67
147
|
- - ">="
|
68
148
|
- !ruby/object:Gem::Version
|
149
|
+
hash: 3
|
69
150
|
segments:
|
70
151
|
- 0
|
71
152
|
version: "0"
|
72
153
|
requirements: []
|
73
154
|
|
74
155
|
rubyforge_project:
|
75
|
-
rubygems_version: 1.
|
156
|
+
rubygems_version: 1.5.2
|
76
157
|
signing_key:
|
77
158
|
specification_version: 3
|
78
|
-
summary: Simple and easy to use Ruby code profiler
|
79
|
-
test_files:
|
80
|
-
|
81
|
-
- spec/no_profile_instance_spec.rb
|
82
|
-
- spec/profile_instance_spec.rb
|
83
|
-
- spec/profile_spec.rb
|
84
|
-
- spec/spec_helper.rb
|
159
|
+
summary: Simple and easy to use Ruby code profiler.
|
160
|
+
test_files: []
|
161
|
+
|
data/README.rdoc
DELETED
@@ -1,248 +0,0 @@
|
|
1
|
-
= easy-prof
|
2
|
-
|
3
|
-
Simple and easy to use Ruby code profiler, which could be used
|
4
|
-
as a Rails plugin.
|
5
|
-
|
6
|
-
== Installation
|
7
|
-
|
8
|
-
There are two options when approaching easy-prof installation:
|
9
|
-
|
10
|
-
* using the gem (recommended)
|
11
|
-
* install as a Rails plugin
|
12
|
-
|
13
|
-
To install as a gem, add this to your environment.rb:
|
14
|
-
|
15
|
-
config.gem 'easy-prof', :lib => 'easy_prof'
|
16
|
-
|
17
|
-
And then run the command:
|
18
|
-
|
19
|
-
sudo rake gems:install
|
20
|
-
|
21
|
-
To install meta-tags as a Rails plugin use this:
|
22
|
-
|
23
|
-
script/plugin install git://github.com/kpumuk/easy-prof.git
|
24
|
-
|
25
|
-
== Description
|
26
|
-
|
27
|
-
The main idea behind the easy-prof is creating check points and your
|
28
|
-
code and measuring time needed to execute code blocks. Here is the
|
29
|
-
example of easy-prof output:
|
30
|
-
|
31
|
-
[home#index] Benchmark results:
|
32
|
-
[home#index] debug: Logged in user home page
|
33
|
-
[home#index] progress: 0.7002 s [find top videos]
|
34
|
-
[home#index] progress: 0.0452 s [build categories list]
|
35
|
-
[home#index] progress: 0.0019 s [build tag cloud]
|
36
|
-
[home#index] progress: 0.0032 s [find featured videos]
|
37
|
-
[home#index] progress: 0.0324 s [find latest videos]
|
38
|
-
[home#index] debug: VIEW STARTED
|
39
|
-
[home#index] progress: 0.0649 s [top videos render]
|
40
|
-
[home#index] progress: 0.0014 s [categories render]
|
41
|
-
[home#index] progress: 2.5887 s [tag cloud render]
|
42
|
-
[home#index] progress: 0.0488 s [latest videos render]
|
43
|
-
[home#index] progress: 0.1053 s [featured video render]
|
44
|
-
[home#index] results: 3.592 s
|
45
|
-
|
46
|
-
From this output you can see what checkpoints takes longer to reach,
|
47
|
-
and what code fragments are pretty fast.
|
48
|
-
|
49
|
-
== Usage
|
50
|
-
|
51
|
-
The library extends <tt>Kernel</tt> with a method <tt>easy_profiler</tt>.
|
52
|
-
By default profiling is disabled globally, so you should pass :enabled
|
53
|
-
parameter to enable profiling of particular code. Also there is a time
|
54
|
-
:limit option which could be used to skip logging of blocks which are
|
55
|
-
fast enough.
|
56
|
-
|
57
|
-
For more details see the options description below.
|
58
|
-
|
59
|
-
easy_profiler('sleep', :enabled => true) do |p|
|
60
|
-
sleep 1
|
61
|
-
p.progress('sleep 1')
|
62
|
-
p.debug('checkpoint reached')
|
63
|
-
sleep 2
|
64
|
-
p.progress('sleep 2')
|
65
|
-
end
|
66
|
-
|
67
|
-
Method accepts two parameters: profiling session name and a hash of
|
68
|
-
options:
|
69
|
-
|
70
|
-
* <tt>:enabled</tt> -- value indicating whether profiling is enabled.
|
71
|
-
* <tt>:limit</tt> -- minimum time period which should be reached to
|
72
|
-
print profiling log.
|
73
|
-
* <tt>:count_ar_instances</tt> -- indicating whether profiler should
|
74
|
-
log an approximate number of instantiated ActiveRecord objects.
|
75
|
-
* <tt>:count_memory_usage</tt> -- indicating whether profiler should
|
76
|
-
log an approximate amount of memory used.
|
77
|
-
* <tt>:logger</tt> -- a +Logger+ instance.
|
78
|
-
|
79
|
-
== Configuration
|
80
|
-
|
81
|
-
There are some global configuration options exists:
|
82
|
-
|
83
|
-
EasyProfiler.configure do |config|
|
84
|
-
config.enable_profiling = false
|
85
|
-
config.print_limit = 0.01
|
86
|
-
config.count_ar_instances = false
|
87
|
-
config.count_memory_usage = false
|
88
|
-
config.logger = nil # or Rails.logger or whatever
|
89
|
-
config.colorize_logging = true
|
90
|
-
config.live_logging = false
|
91
|
-
end
|
92
|
-
|
93
|
-
* <tt>enable_profiling</tt> -- used to enable or disable profiling
|
94
|
-
globalle (<tt>false</tt> by default).
|
95
|
-
* <tt>print_limit</tt> -- used to set a minimum time period in seconds
|
96
|
-
which should be reached to dump profile to the log (<tt>0.01</tt>
|
97
|
-
by default).
|
98
|
-
* <tt>count_ar_instances</tt> -- indicating whether profiler should
|
99
|
-
log an approximate number of instantiated ActiveRecord objects.
|
100
|
-
* <tt>count_memory_usage</tt> -- indicating whether profiler should
|
101
|
-
log an approximate amount of memory used.
|
102
|
-
* <tt>logger</tt> -- a <tt>Logger</tt> instance to dump logs to.
|
103
|
-
* <tt>colorize_logging</tt> -- when <tt>true</tt>, output will be
|
104
|
-
colorized (useful when dumping profiling information into the
|
105
|
-
Rails log).
|
106
|
-
* <tt>live_logging</tt> -- when <tt>true</tt>, every profiling info
|
107
|
-
will be pushed to the log immediately (by default everything will
|
108
|
-
be dumped in the end of profiling session).
|
109
|
-
|
110
|
-
== Active Record instances number profiling
|
111
|
-
|
112
|
-
easy-prof can log a number of instantiated ActiveRecord instances.
|
113
|
-
To enable this kind of profiling, use a <tt>:count_ar_instances</tt>
|
114
|
-
option or global setting with the same name.
|
115
|
-
|
116
|
-
Please note, that easy-prof completely disables garbage collector
|
117
|
-
during this kind of profiling. It could hurt your overall application
|
118
|
-
performance, so do not use it on production boxes. Also I can't
|
119
|
-
guaranty 100% precision, but it is about this value in almost all
|
120
|
-
cases.
|
121
|
-
|
122
|
-
Further reading:
|
123
|
-
* That’s Not a Memory Leak, It’s Bloat http://www.engineyard.com/blog/2009/thats-not-a-memory-leak-its-bloat/
|
124
|
-
|
125
|
-
== Memory usage profiling
|
126
|
-
|
127
|
-
The plugin is able to log an amount of memory used by current Ruby
|
128
|
-
process. To enable this kind of profiling, use a <tt>:count_memory_usage</tt>
|
129
|
-
option or global setting with the same name.
|
130
|
-
|
131
|
-
Please note, that easy-prof completely disables garbage collector
|
132
|
-
during this kind of profiling. It could hurt your overall application
|
133
|
-
performance, so do not use it on production boxes. Also I can't
|
134
|
-
guaranty 100% precision, but it is about this value in almost all
|
135
|
-
cases.
|
136
|
-
|
137
|
-
== Dumping results to the Firebug console
|
138
|
-
|
139
|
-
If you are profiling a Ruby on Rails application, it could be useful
|
140
|
-
to get profiling results from production server sometimes. To achieve
|
141
|
-
this you can use a <tt>FirebugLogger</tt>, bundled with this plugin.
|
142
|
-
In any controller you have a helper called <tt>firebug_logger</tt>,
|
143
|
-
so you can pass it to EasyProfiler using <tt>:logger</tt> option:
|
144
|
-
|
145
|
-
easy_profiler('home#index', :logger => firebug_logger, :limit => 2) do |p|
|
146
|
-
end
|
147
|
-
|
148
|
-
The idea behind this logger is pretty simple (as everything in this
|
149
|
-
plugin): there is an <tt>after_filter</tt> named <tt>dump_firebug_profile</tt>,
|
150
|
-
which dumps profiling information after your action finished its work.
|
151
|
-
Please note: it will not output any line when profiling session is
|
152
|
-
disabled or time limit is not reached.
|
153
|
-
|
154
|
-
Do not forget to protect firebug output: it is a bad idea to allow
|
155
|
-
anyone to see your profiling session dump. You can allow admin
|
156
|
-
users only to use firebug, or restrict this feature by IP address.
|
157
|
-
|
158
|
-
BTW, you can use Firebug Console Lite (http://getfirebug.com/lite.html)
|
159
|
-
to get this feature working in any browser! By default it works
|
160
|
-
perfectly in Firefox with Firebug installed, and in Safari 4.
|
161
|
-
|
162
|
-
== Ruby on Rails application profiling
|
163
|
-
|
164
|
-
Here is the complete example of a Rails action profiling:
|
165
|
-
|
166
|
-
class HomeController < ApplicationController
|
167
|
-
def index
|
168
|
-
easy_profiler('home#index', :enabled => profile_request?, :limit => 2) do |p|
|
169
|
-
p.progress 'logged in user home page'
|
170
|
-
|
171
|
-
@top_videos = Video.top(:limit => 10)
|
172
|
-
p.progress 'find top videos'
|
173
|
-
|
174
|
-
@categories = Category.all(:order => 'name DESC')
|
175
|
-
p.progress 'build categories list'
|
176
|
-
|
177
|
-
@tag_cloud = Tag.tag_cloud(:limit => 200)
|
178
|
-
p.progress 'build tag cloud'
|
179
|
-
|
180
|
-
@featured_videos = Video.featured(limit => 5)
|
181
|
-
p.progress 'find featured videos'
|
182
|
-
|
183
|
-
@latest_videos = Video.latest(:limit => 5)
|
184
|
-
p.progress 'find latest videos'
|
185
|
-
|
186
|
-
@profiler = p
|
187
|
-
p.debug 'VIEW STARTED'
|
188
|
-
end
|
189
|
-
end
|
190
|
-
|
191
|
-
private
|
192
|
-
|
193
|
-
# Method returns +true+ if current request should ouput profiling information
|
194
|
-
def profile_request?
|
195
|
-
params['_with_profiling'] == 'yes'
|
196
|
-
end
|
197
|
-
end
|
198
|
-
|
199
|
-
And view:
|
200
|
-
|
201
|
-
<div id="top_videos">
|
202
|
-
<%= render :partial => 'top_videos' %>
|
203
|
-
<% @profiler.progress 'top videos render' %>
|
204
|
-
</div>
|
205
|
-
|
206
|
-
<div class="tabs">
|
207
|
-
<ul id="taxonomy">
|
208
|
-
<li><a href="#" id="categories" class="current">Categories</a></li>
|
209
|
-
<li><a href="#" id="tags">Tags</a></li>
|
210
|
-
</ul>
|
211
|
-
<div class="categories_panel">
|
212
|
-
<%= render :partial => 'categories' %>
|
213
|
-
<% @profiler.progress 'categories render' %>
|
214
|
-
</div>
|
215
|
-
<div class="categories_panel hidden">
|
216
|
-
<%= render :partial => 'tag_cloud' %>
|
217
|
-
<% @profiler.progress 'tag cloud render' %>
|
218
|
-
</div>
|
219
|
-
</div>
|
220
|
-
|
221
|
-
<div class="box">
|
222
|
-
<div id="latest">
|
223
|
-
<%= render :partial => 'videos', :videos => @latest_videos %>
|
224
|
-
<% @profiler.progress 'latest videos render' %>
|
225
|
-
</div>
|
226
|
-
<div id="featured">
|
227
|
-
<%= render :partial => 'videos', :videos => @featured_videos %>
|
228
|
-
<% @profiler.progress 'featured video render' %>
|
229
|
-
</div>
|
230
|
-
</div>
|
231
|
-
|
232
|
-
As you can see from this example, profiler will be enabled only when
|
233
|
-
you pass a _with_profiling parameter with value yes:
|
234
|
-
|
235
|
-
http://example.com/home?_with_profiling=yes
|
236
|
-
|
237
|
-
== Who are the authors?
|
238
|
-
|
239
|
-
This plugin has been created in Scribd.com for our internal use
|
240
|
-
and then the sources were opened for other people to use. All the
|
241
|
-
code in this package has been developed by Dmytro Shteflyuk for
|
242
|
-
Scribd.com and is released under the MIT license. For more details,
|
243
|
-
see the MIT-LICENSE file.
|
244
|
-
|
245
|
-
== Credits
|
246
|
-
|
247
|
-
* Dmytro Shteflyuk (author) <kpumuk@kpumuk.info> http://kpumuk.info
|
248
|
-
* Alexey Kovyrin (contributor) <alexey@kovyrin.net> http://kovyrin.net
|
data/VERSION.yml
DELETED
data/init.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require 'easy_prof'
|