Class: Perf::Meter
- Inherits:
-
Object
- Object
- Perf::Meter
- Defined in:
- lib/perf/meter.rb
Overview
Measures the runtime execution speed of a block of code, expression or entire methods.
Constant Summary collapse
- ACCURACY_UNKNOWN =
Constant for accuracy. The constant represents the upper bound of its description.
0.0
- ACCURACY_VERY_POOR =
1.0
- ACCURACY_POOR =
50.0
- ACCURACY_FAIR =
100.0
- ACCURACY_GOOD =
1000.0
- ACCURACY_EXCELLENT =
1.0/0
- PATH_MEASURES =
Name of the path roots
'\blocks'
- PATH_METHODS =
'\methods'
- METHOD_TYPE_INSTANCE =
Hash keys for instrumented methods
:instance
- METHOD_TYPE_CLASS =
:class
- OVERHEAD_CALC_MAX_REPETITIONS =
Overhead calculation tuning constants
1000
- OVERHEAD_CALC_RUNS =
10
- OVERHEAD_CALC_MIN_TIME =
0.1
- @@overhead =
nil
Instance Attribute Summary collapse
-
#current_path ⇒ Object
Returns the value of attribute current_path.
-
#measurements ⇒ Object
Returns the value of attribute measurements.
Instance Method Summary collapse
-
#accuracy(path) ⇒ Object
Returns an index of accuracy of the measure calculated in relation to the overhead.
-
#adjust_overhead ⇒ Object
The overhead cannot be larger that any of the measures taken.
- #adjusted_time(m) ⇒ Object
-
#blocks_time ⇒ Object
Returns the total time - expressed with a Benchmark::Tms object - for all the blocks measures.
- #has_measures? ⇒ Boolean
-
#initialize(options = {}) ⇒ Meter
constructor
Creation of a Perf::Meter allows you to specify if you want to consider the overhead in the calculation or not.
-
#measure(what, root_path = PATH_MEASURES, &code) ⇒ Object
Takes a description and a code block and measures the performance of the block.
-
#measure_class_method(klass, method_name) ⇒ Object
Puts a wrapper around class methods of a specific class to measure their performance Remember to use restore_class_method when you are done, otherwise the class method will stay instrumented.
-
#measure_instance_method(klass, method_name) ⇒ Object
Puts a wrapper around instance methods of a specific class to measure their performance Remember to use restore_instance_method when you are done, otherwise the method will stay instrumented.
-
#measure_result(what, &code) ⇒ Object
Takes a description and an expression returning a value and measures the performance of the expression storing the result by returned value.
-
#method_meters(klass, imethods = [], cmethods = []) ⇒ Object
Puts a wrapper around a set of methods of a specific class to measure their performance.
-
#methods_time ⇒ Object
Returns the total time - expressed with a Benchmark::Tms object - for all the methods measures.
- #overhead ⇒ Object
-
#restore_all_class_methods(klass) ⇒ Object
Removes the instrumentation of all class methods in a given class.
-
#restore_all_instance_methods(klass) ⇒ Object
Removes all instrumentation of instance methods in a given class.
-
#restore_all_methods(klass) ⇒ Object
Removes all instrumentation of class methods and instance methods in a given class.
-
#restore_class_method(klass, method_name) ⇒ Object
Removes the instrumentation of a class method in a given class.
-
#restore_instance_method(klass, method_name) ⇒ Object
Removes the instrumentation of a instance method in a given class.
Constructor Details
#initialize(options = {}) ⇒ Meter
Creation of a Perf::Meter allows you to specify if you want to consider the overhead in the calculation or not. The overhead is calculated once and stored away. That way it is always the same in a single run.
44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/perf/meter.rb', line 44 def initialize(={}) @options = .clone @options[:subtract_overhead] = true if @options[:subtract_overhead].nil? # Never use ||= with booleans @measurements = {} # A hash of Measure @current_path = nil @instrumented_methods = {METHOD_TYPE_INSTANCE=>[],METHOD_TYPE_CLASS=>[]} @subtract_overhead = @options[:subtract_overhead] if @@overhead.nil? @@overhead = measure_overhead @measurements = {} # A hash of Measure; must repeat here to cleanup what measure_overhead did end end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method_sym, *arguments, &block) ⇒ Object (protected)
You can generate a report using one of the built-in report formats with a simple syntax shortcut
m=Perf::Meter.new
m.report_FORMAT
Where FORMAT is the ending part of one of the ReportFormatFORMAT classes built in.
Examples
m=Perf::Meter.new m.measure(:something) something puts m.report_html puts m.report_simple
473 474 475 476 477 478 479 |
# File 'lib/perf/meter.rb', line 473 def method_missing(method_sym, *arguments, &block) if method_sym.to_s =~ /^report_(.*)$/ klass=Object.const_get("Perf").const_get("ReportFormat#{camelize($1)}") return klass.new.format(self,arguments[0]) if klass end super end |
Instance Attribute Details
#current_path ⇒ Object
Returns the value of attribute current_path.
32 33 34 |
# File 'lib/perf/meter.rb', line 32 def current_path @current_path end |
#measurements ⇒ Object
Returns the value of attribute measurements.
31 32 33 |
# File 'lib/perf/meter.rb', line 31 def measurements @measurements end |
Instance Method Details
#accuracy(path) ⇒ Object
Returns an index of accuracy of the measure calculated in relation to the overhead. The larger the accuracy, the more accurate the measure. accuracy < 0 means that it is not possible to calculate; accuracy <= 1 means that the measure is equal or smaller than the overhead.
This makes the measure very inaccurate.
accuracy = X means that the measure is X times the overhead.
346 347 348 349 350 351 352 353 354 355 |
# File 'lib/perf/meter.rb', line 346 def accuracy(path) if @@overhead over=@@overhead[:time].total+@@overhead[:time].real if over>0 m=get_measurement(path) return ((m.time.total+m.time.real)*@@overhead[:count] / (over*m.count)) if m.count>0 end end -1.0 end |
#adjust_overhead ⇒ Object
The overhead cannot be larger that any of the measures taken. If a measure taken is larger than the overhead, than this function takes care of adjusting the overhead. This is called by the ReportFormat class just before rendering the report, so you should not have to call this by hand unless you are interested in getting the overhead.
362 363 364 |
# File 'lib/perf/meter.rb', line 362 def adjust_overhead false end |
#adjusted_time(m) ⇒ Object
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/perf/meter.rb', line 67 def adjusted_time(m) return m.time if !@subtract_overhead || !@overhead utime,stime,cutime,cstime,real = nil,nil,nil,nil,nil adj=m.time-((@overhead[:time]*m.count)/@overhead[:count]) utime = 0.0 if adj.utime < 0.0 stime = 0.0 if adj.stime < 0.0 cutime = 0.0 if adj.cutime < 0.0 cstime = 0.0 if adj.cstime < 0.0 real = 0.0 if adj.real < 0.0 if utime || stime || cutime || cstime || real Benchmark::Tms.new(utime || adj.utime, stime || adj.stime, cutime || adj.cutime, cstime || adj.cstime, real || adj.real) else adj end end |
#blocks_time ⇒ Object
Returns the total time - expressed with a Benchmark::Tms object - for all the blocks measures
96 97 98 |
# File 'lib/perf/meter.rb', line 96 def blocks_time @measurements[PATH_MEASURES].time if @measurements[PATH_MEASURES] end |
#has_measures? ⇒ Boolean
91 92 93 |
# File 'lib/perf/meter.rb', line 91 def has_measures? @measurements.length > 0 end |
#measure(what, root_path = PATH_MEASURES, &code) ⇒ Object
Takes a description and a code block and measures the performance of the block. It returns the value returned by the block
Attributes
-
what
- The title that will identify of the block -
code
- Block of code to measure
Examples
Measures the time taken by the code in the block
perf = Perf::Meter.new
perf.measure(:func) do
some code here
end
Measure the time taken to compute “some_expression”
if perf.measure(:some_expression) { some_expression }
...
end
Measure a bunch of things, and divides the measures in sub blocks that get measures separately
perf.measure(:bunch_of_stuff) do
perf.measure(:thing1) do
...
end
perf.measure(:thing2) do
perf.measure(:thing2_part1) do
...
end
perf.measure(:thing2_part2) do
...
end
end
end
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/perf/meter.rb', line 145 def measure(what,root_path=PATH_MEASURES,&code) current_path=@current_path if @current_path.nil? @current_path=root_path root=get_measurement(@current_path) else root=nil end @current_path+= "\\#{what}" res=nil begin m=get_measurement(@current_path) m.count += 1 root.count += 1 if root m.measuring +=1 if m.measuring>1 res=code.call else t = Benchmark.measure { res=code.call } root.time += t if root m.time += t end ensure @current_path=current_path m.measuring-=1 end res end |
#measure_class_method(klass, method_name) ⇒ Object
Puts a wrapper around class methods of a specific class to measure their performance Remember to use restore_class_method when you are done, otherwise the class method will stay instrumented.
Use sparingly!
Attributes
-
klass
- The Class containing the instance method that you want to measure -
method_name
- The name of the class method that you want to measure
Examples
Instruments the class find so that the execution of the class method “static_method” will be measures every time that is used.
perf = Perf::Meter.new
perf.measure_class_method(SomeClass,:static_method)
..
Removes the instrumentation (important!)
perf.restore_class_method(SomeClass,:static_method)
Removes all instrumentation from class SomeClass
perf.restore_all_class_methods(SomeClass)
313 314 315 |
# File 'lib/perf/meter.rb', line 313 def measure_class_method(klass,method_name) measure_method_by_type(class << klass; self end,method_name,METHOD_TYPE_CLASS) end |
#measure_instance_method(klass, method_name) ⇒ Object
Puts a wrapper around instance methods of a specific class to measure their performance Remember to use restore_instance_method when you are done, otherwise the method will stay instrumented.
Use sparingly!
Attributes
-
klass
- The Class containing the instance method that you want to measure -
method_name
- The name of the method that you want to measure
Examples
Instruments the class find so that the execution of the method “find” will be measures every time that is used.
perf = Perf::Meter.new
perf.measure_instance_method(User,:find)
..
Removes the instrumentation (important!)
perf.restore_instance_method(User,:find)
Removes all instrumentation from class User
perf.restore_all_instance_methods(User)
268 269 270 |
# File 'lib/perf/meter.rb', line 268 def measure_instance_method(klass,method_name) measure_method_by_type(klass,method_name,METHOD_TYPE_INSTANCE) end |
#measure_result(what, &code) ⇒ Object
Takes a description and an expression returning a value and measures the performance of the expression storing the result by returned value. Should be used only for expressions that can return only a small discrete number of unique values, such a flag for example.
It returns the value returned by the block
Attributes
-
what
- The title that will identify of the block -
code
- Block of code to measure
Examples
Measures the time take to compute the existence of user xyz and will give you stats for the case in which the result is true and false.
perf = Perf::Meter.new
if perf.measure_result(:long_epression) { User.find(xyz).nil? }
end
195 196 197 198 199 |
# File 'lib/perf/meter.rb', line 195 def measure_result(what,&code) res=measure(what,PATH_MEASURES,&code) merge_measures(what,"#{what} = \"#{res.to_s}\"") res end |
#method_meters(klass, imethods = [], cmethods = []) ⇒ Object
Puts a wrapper around a set of methods of a specific class to measure their performance. The set is provided with an array of instance methods, and one of class methods.
The method defines the wrapper, yields to the block, and then restores the instrumented class. This ensures that the instrumented class is restored, and that the instrumentation occurs only in the context of the block
Attributes
-
klass
- The Class containing the instance method that you want to measure -
imethods
- An array of instance methods that you want to measure -
cmethods
- An array of class methods that you want to measure
Examples
perf = Perf::Meter.new
m.method_meters(PerfTestExample,[:test,:test_np],[:static_method]) do
a=PerfTestExample.new
a.test(1,2,3)
a.test_np
PerfTestExample.static_method
end
After this m contains measures for the executions of the instance methods test, test_np and the class methods static_method
228 229 230 231 232 233 234 235 236 237 238 239 |
# File 'lib/perf/meter.rb', line 228 def method_meters(klass,imethods=[],cmethods=[]) res=nil begin imethods.each {|m| measure_instance_method(klass,m) } cmethods.each {|m| measure_class_method(klass,m) } res=yield ensure imethods.each {|m| restore_instance_method(klass,m) } cmethods.each {|m| restore_class_method(klass,m) } end res end |
#methods_time ⇒ Object
Returns the total time - expressed with a Benchmark::Tms object - for all the methods measures
101 102 103 |
# File 'lib/perf/meter.rb', line 101 def methods_time @measurements[PATH_METHODS].time if @measurements[PATH_METHODS] end |
#overhead ⇒ Object
59 60 61 62 63 64 65 |
# File 'lib/perf/meter.rb', line 59 def overhead if @subtract_overhead @@overhead.dup else {:time=>Benchmark::Tms.new,:count=>0} end end |
#restore_all_class_methods(klass) ⇒ Object
Removes the instrumentation of all class methods in a given class. See measure_class_method for more information.
327 328 329 |
# File 'lib/perf/meter.rb', line 327 def restore_all_class_methods(klass) restore_all_methods_by_type(class << klass; self end,METHOD_TYPE_CLASS) end |
#restore_all_instance_methods(klass) ⇒ Object
Removes all instrumentation of instance methods in a given class. See measure_instance_method for more information.
282 283 284 |
# File 'lib/perf/meter.rb', line 282 def restore_all_instance_methods(klass) restore_all_methods_by_type(klass,METHOD_TYPE_INSTANCE) end |
#restore_all_methods(klass) ⇒ Object
Removes all instrumentation of class methods and instance methods in a given class. See measure_class_method for more information.
334 335 336 337 |
# File 'lib/perf/meter.rb', line 334 def restore_all_methods(klass) restore_all_instance_methods(klass) restore_all_class_methods(klass) end |
#restore_class_method(klass, method_name) ⇒ Object
Removes the instrumentation of a class method in a given class. See measure_class_method for more information.
320 321 322 |
# File 'lib/perf/meter.rb', line 320 def restore_class_method(klass,method_name) restore_method_by_type(class << klass; self end,method_name,METHOD_TYPE_CLASS) end |
#restore_instance_method(klass, method_name) ⇒ Object
Removes the instrumentation of a instance method in a given class. See measure_instance_method for more information.
275 276 277 |
# File 'lib/perf/meter.rb', line 275 def restore_instance_method(klass,method_name) restore_method_by_type(klass,method_name,METHOD_TYPE_INSTANCE) end |