benchmarkable 1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +54 -0
- data/lib/benchmarkable.rb +141 -0
- data/spec/benchmarkable_spec.rb +270 -0
- metadata +57 -0
data/README
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
BENCHMARKABLE
|
2
|
+
by Aman King
|
3
|
+
|
4
|
+
http://bitbucket.org/amanking/benchmarkable/
|
5
|
+
|
6
|
+
A module that allows a class to mention which instance methods to benchmark, and then allows retrieving the benchmark report in csv format from the class's instances. The csv includes the method invocation timestamp, some context description (if provided), the method name along with arguments passed for the invocation, and the number of seconds the method took to execute.
|
7
|
+
|
8
|
+
Eg:
|
9
|
+
class Gateway
|
10
|
+
# ...
|
11
|
+
def make_request(url)
|
12
|
+
url = URI.parse(url)
|
13
|
+
Net::HTTP.start(url.host, url.port) {|http|
|
14
|
+
http.get('/index.html')
|
15
|
+
}
|
16
|
+
rescue => error
|
17
|
+
puts "Unexpected error: #{error.message}"
|
18
|
+
end
|
19
|
+
# ...
|
20
|
+
|
21
|
+
include Benchmarkable
|
22
|
+
benchmark :make_request
|
23
|
+
end
|
24
|
+
|
25
|
+
gateway = Gateway.new
|
26
|
+
gateway.make_request('http://www.google.com/')
|
27
|
+
gateway.make_request('http://www.yahoo.com/')
|
28
|
+
gateway.make_request('http://www.wikyblog.com/AmanKing/')
|
29
|
+
File.open('./gateway_performance_report.csv', 'a+') do |file|
|
30
|
+
file.puts gateway.benchmark_report.to_csv(:starting_context => 'gateway')
|
31
|
+
end
|
32
|
+
|
33
|
+
Output (in gateway_performance_report.csv):
|
34
|
+
"2009-09-10T20:13:59+05:30","gateway","make_request http://www.google.com/","0.306514978408813"
|
35
|
+
"2009-09-10T20:13:59+05:30","gateway","make_request http://www.yahoo.com/","1.08063411712646"
|
36
|
+
"2009-09-10T20:14:00+05:30","gateway","make_request http://www.wikyblog.com/AmanKing/","2.1521680355072"
|
37
|
+
|
38
|
+
(see samples/ajaxy_blog_spec.rb for an example of how to use Benchmarkable to monitor ajax performance using selenium, and look at spec/benchmarkable_spec.rb for more details about the api)
|
39
|
+
|
40
|
+
License
|
41
|
+
|
42
|
+
Copyright 2009 Aman King
|
43
|
+
|
44
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
45
|
+
you may not use this file except in compliance with the License.
|
46
|
+
You may obtain a copy of the License at
|
47
|
+
|
48
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
49
|
+
|
50
|
+
Unless required by applicable law or agreed to in writing, software
|
51
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
52
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
53
|
+
See the License for the specific language governing permissions and
|
54
|
+
limitations under the License.
|
@@ -0,0 +1,141 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright 2009 Aman King
|
3
|
+
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
you may not use this file except in compliance with the License.
|
6
|
+
You may obtain a copy of the License at
|
7
|
+
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
See the License for the specific language governing permissions and
|
14
|
+
limitations under the License.
|
15
|
+
=end
|
16
|
+
|
17
|
+
require 'benchmark'
|
18
|
+
require 'date'
|
19
|
+
require 'faster_csv'
|
20
|
+
|
21
|
+
module Benchmarkable
|
22
|
+
def self.included(klass)
|
23
|
+
klass.extend(ClassMethods)
|
24
|
+
end
|
25
|
+
|
26
|
+
module ClassMethods
|
27
|
+
def benchmark(*methods_with_description)
|
28
|
+
methods_with_description.each do |method_with_description|
|
29
|
+
if method_with_description.kind_of?(Hash)
|
30
|
+
method_with_description.each_pair {|method_name, description| decorate_for_benchmarking(method_name, description) }
|
31
|
+
else
|
32
|
+
decorate_for_benchmarking(method_with_description, method_with_description)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
def decorate_for_benchmarking(method_name, description)
|
39
|
+
return if method_name.to_s =~ /(=|\+|-|\[\]|\*|\/|<<|>>|<|>)/ || method_name.to_s =~ /with(out)?_benchmarking$/
|
40
|
+
|
41
|
+
with_feature_method_name, without_feature_method_name = with_and_without_feature_method_names(method_name, "benchmarking")
|
42
|
+
return if instance_methods.include?(with_feature_method_name)
|
43
|
+
|
44
|
+
class_eval <<-EOS
|
45
|
+
def #{with_feature_method_name}(*args, &block)
|
46
|
+
benchmark_report.add_entry_for("#{description} \#{args.join(', ')}".strip) do
|
47
|
+
#{without_feature_method_name}(*args, &block)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
EOS
|
51
|
+
alias_method_chain method_name, :benchmarking
|
52
|
+
end
|
53
|
+
|
54
|
+
unless self.respond_to?(:alias_method_chain)
|
55
|
+
def alias_method_chain(method_name, feature)
|
56
|
+
with_feature_method_name, without_feature_method_name = with_and_without_feature_method_names(method_name, feature)
|
57
|
+
alias_method without_feature_method_name, method_name
|
58
|
+
alias_method method_name, with_feature_method_name
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def with_and_without_feature_method_names(method_name, feature)
|
63
|
+
method_name = method_name.to_s
|
64
|
+
if method_name =~ /(!|\?)$/
|
65
|
+
return ["#{method_name[0...-1]}_with_#{feature}#{$1}", "#{method_name[0...-1]}_without_#{feature}#{$1}"]
|
66
|
+
end
|
67
|
+
["#{method_name}_with_#{feature}", "#{method_name}_without_#{feature}"]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def benchmark_report
|
72
|
+
@benchmark_report ||= BenchmarkReport.new
|
73
|
+
end
|
74
|
+
|
75
|
+
class BenchmarkReport
|
76
|
+
def add_entry_for(description)
|
77
|
+
result = nil
|
78
|
+
call_stack << []
|
79
|
+
data = Data.new(description) do
|
80
|
+
result = yield
|
81
|
+
end
|
82
|
+
call_stack.pop.each {|nested_call_data| data << nested_call_data }
|
83
|
+
call_stack.last << data
|
84
|
+
result
|
85
|
+
end
|
86
|
+
|
87
|
+
def to_csv(options = {})
|
88
|
+
csv_options = {:force_quotes => true, :encoding => 'U'}.merge(options.delete(:csv_options) || {})
|
89
|
+
FasterCSV.generate(csv_options) do |csv|
|
90
|
+
entries(options).each do |entry|
|
91
|
+
csv << [entry[:timestamp].to_s, entry[:context], entry[:execution_time].real].flatten
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def entries(options = {})
|
97
|
+
starting_context = options[:starting_context].to_a || []
|
98
|
+
nesting_limit = options[:nesting_limit] == :none ? call_stack.first.collect {|data| data.nested_levels }.max : options[:nesting_limit] || 0
|
99
|
+
call_stack.first.collect {|data| data.to_entry(starting_context, nesting_limit) }.flatten
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
def call_stack
|
104
|
+
scope_for_top_level_calls = []
|
105
|
+
@call_stack ||= [scope_for_top_level_calls]
|
106
|
+
end
|
107
|
+
|
108
|
+
class Data
|
109
|
+
def initialize(description)
|
110
|
+
@description = description
|
111
|
+
@timestamp = DateTime.now
|
112
|
+
@overall_time = Benchmark.measure do
|
113
|
+
yield
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def <<(data_for_nested_call)
|
118
|
+
data_for_nested_calls << data_for_nested_call
|
119
|
+
end
|
120
|
+
|
121
|
+
def to_entry(context_so_far = [], nesting_limit = 0)
|
122
|
+
current_context = context_so_far + [@description]
|
123
|
+
empty_context_columns = nesting_limit > 0 ? ['-'] * [nesting_limit, nested_levels].max : []
|
124
|
+
current_entry = {:timestamp => @timestamp, :context => current_context + empty_context_columns, :execution_time => @overall_time}
|
125
|
+
nested_entries = nesting_limit == 0 ? [] :
|
126
|
+
data_for_nested_calls.collect {|nested_call_data| nested_call_data.to_entry(current_context, nesting_limit - 1)}.flatten
|
127
|
+
[current_entry] + nested_entries
|
128
|
+
end
|
129
|
+
|
130
|
+
def nested_levels
|
131
|
+
return 0 if data_for_nested_calls.empty?
|
132
|
+
1 + data_for_nested_calls.collect {|nested_call_data| nested_call_data.nested_levels }.max
|
133
|
+
end
|
134
|
+
|
135
|
+
protected
|
136
|
+
def data_for_nested_calls
|
137
|
+
@data_for_nested_calls ||= []
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,270 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright 2009 Aman King
|
3
|
+
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
you may not use this file except in compliance with the License.
|
6
|
+
You may obtain a copy of the License at
|
7
|
+
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
See the License for the specific language governing permissions and
|
14
|
+
limitations under the License.
|
15
|
+
=end
|
16
|
+
|
17
|
+
require 'spec'
|
18
|
+
require File.join(File.dirname(__FILE__), '../lib/benchmarkable')
|
19
|
+
|
20
|
+
describe Benchmarkable do
|
21
|
+
before(:each) do
|
22
|
+
@klass = Class.new { include Benchmarkable }
|
23
|
+
end
|
24
|
+
|
25
|
+
describe 'alias methods' do
|
26
|
+
it 'should be created for a method with a normal name' do
|
27
|
+
@klass.class_eval do
|
28
|
+
def some_method(*args); end
|
29
|
+
benchmark :some_method
|
30
|
+
end
|
31
|
+
|
32
|
+
@klass.new.should respond_to(:some_method)
|
33
|
+
@klass.new.should respond_to(:some_method_with_benchmarking)
|
34
|
+
@klass.new.should respond_to(:some_method_without_benchmarking)
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should be created for a method with a ! suffix' do
|
38
|
+
@klass.class_eval do
|
39
|
+
def some_method!(*args); end
|
40
|
+
benchmark :some_method!
|
41
|
+
end
|
42
|
+
|
43
|
+
@klass.new.should respond_to(:some_method!)
|
44
|
+
@klass.new.should respond_to(:some_method_with_benchmarking!)
|
45
|
+
@klass.new.should respond_to(:some_method_without_benchmarking!)
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should be created for a method with a ? suffix' do
|
49
|
+
@klass.class_eval do
|
50
|
+
def some_method?(*args); end
|
51
|
+
benchmark :some_method?
|
52
|
+
end
|
53
|
+
|
54
|
+
@klass.new.should respond_to(:some_method?)
|
55
|
+
@klass.new.should respond_to(:some_method_with_benchmarking?)
|
56
|
+
@klass.new.should respond_to(:some_method_without_benchmarking?)
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should not be created for a method with a = suffix' do
|
60
|
+
@klass.class_eval do
|
61
|
+
def some_method=(*args); end
|
62
|
+
benchmark :some_method=
|
63
|
+
end
|
64
|
+
|
65
|
+
@klass.new.should respond_to(:some_method=)
|
66
|
+
@klass.new.should_not respond_to(:some_method_with_benchmarking=)
|
67
|
+
@klass.new.should_not respond_to(:some_method_without_benchmarking=)
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should not be created for operators' do
|
71
|
+
@klass.class_eval do
|
72
|
+
operators = [:==, :+, :-, :[], :*, :/, :<<, :>>, :<, :>]
|
73
|
+
operators.each do |operator|
|
74
|
+
define_method(operator) {}
|
75
|
+
end
|
76
|
+
benchmark *operators
|
77
|
+
end
|
78
|
+
|
79
|
+
[:==, :+, :-, :[], :*, :/, :<<, :>>, :<, :>].each do |operator|
|
80
|
+
@klass.new.should respond_to(operator)
|
81
|
+
@klass.new.should_not respond_to("#{operator}_with_benchmarking")
|
82
|
+
@klass.new.should_not respond_to("#{operator}_without_benchmarking")
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'should not be created for a decorating method (with a with_benchmarking or without_benchmarking suffix)' do
|
87
|
+
@klass.class_eval do
|
88
|
+
def some_method_with_benchmarking(*args); end
|
89
|
+
def some_method_without_benchmarking(*args); end
|
90
|
+
benchmark :some_method_with_benchmarking, :some_method_without_benchmarking
|
91
|
+
end
|
92
|
+
|
93
|
+
[:some_method_with_benchmarking, :some_method_without_benchmarking].each do |method_name|
|
94
|
+
@klass.new.should respond_to(method_name)
|
95
|
+
@klass.new.should_not respond_to("#{method_name}_with_benchmarking")
|
96
|
+
@klass.new.should_not respond_to("#{method_name}_without_benchmarking")
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'should benchmark a method using the method name as context' do
|
103
|
+
@klass.class_eval do
|
104
|
+
def some_method(*args); 'something'; end
|
105
|
+
benchmark :some_method
|
106
|
+
end
|
107
|
+
|
108
|
+
DateTime.stub!(:now).and_return(:time1)
|
109
|
+
Benchmark.should_receive(:measure).and_yield.and_return(:measured_time)
|
110
|
+
instance = @klass.new
|
111
|
+
instance.some_method('arg1', 'arg2').should == 'something'
|
112
|
+
instance.benchmark_report.entries.should == [{:timestamp => :time1, :context =>['some_method arg1, arg2'], :execution_time => :measured_time }]
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'should not interfere with the functionality of the original method' do
|
116
|
+
@klass.class_eval do
|
117
|
+
def some_method(*args); 'something'; end
|
118
|
+
benchmark :some_method
|
119
|
+
end
|
120
|
+
|
121
|
+
@klass.new.some_method('arg1', 'arg2').should == 'something'
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'should not decorate a method for benchmarking more than once' do
|
125
|
+
@klass.class_eval do
|
126
|
+
def some_method(*args); 'something'; end
|
127
|
+
benchmark :some_method, :some_method
|
128
|
+
end
|
129
|
+
|
130
|
+
lambda { @klass.new.some_method('arg1', 'arg2') }.should_not raise_error
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'should benchmark a method using the specified context message' do
|
134
|
+
@klass.class_eval do
|
135
|
+
def some_method(*args); 'something'; end
|
136
|
+
benchmark :some_method => 'context 1'
|
137
|
+
end
|
138
|
+
|
139
|
+
DateTime.stub!(:now).and_return(:time1)
|
140
|
+
Benchmark.should_receive(:measure).and_yield.and_return(:measured_time)
|
141
|
+
instance = @klass.new
|
142
|
+
instance.some_method('arg1', 'arg2')
|
143
|
+
instance.benchmark_report.entries.should == [{:timestamp => :time1, :context =>['context 1 arg1, arg2'], :execution_time => :measured_time }]
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'should benchmark a method using the specified context message after the starting context' do
|
147
|
+
@klass.class_eval do
|
148
|
+
def some_method(*args); 'something'; end
|
149
|
+
benchmark :some_method => 'context 1'
|
150
|
+
end
|
151
|
+
|
152
|
+
DateTime.stub!(:now).and_return(:time1)
|
153
|
+
Benchmark.should_receive(:measure).and_yield.and_return(:measured_time)
|
154
|
+
instance = @klass.new
|
155
|
+
instance.some_method('arg1', 'arg2')
|
156
|
+
|
157
|
+
instance.benchmark_report.entries(:starting_context => 'my context').should ==
|
158
|
+
[{:timestamp => :time1, :context =>['my context', 'context 1 arg1, arg2'], :execution_time => :measured_time }]
|
159
|
+
|
160
|
+
instance.benchmark_report.entries(:starting_context => ['my context1', 'my context2']).should ==
|
161
|
+
[{:timestamp => :time1, :context =>['my context1', 'my context2', 'context 1 arg1, arg2'], :execution_time => :measured_time }]
|
162
|
+
end
|
163
|
+
|
164
|
+
it 'should benchmark multiple methods' do
|
165
|
+
@klass.class_eval do
|
166
|
+
def some_method(*args); 'something'; end
|
167
|
+
def another_method; 'another'; end
|
168
|
+
benchmark :another_method, :some_method => 'context 1'
|
169
|
+
end
|
170
|
+
|
171
|
+
DateTime.stub!(:now).and_return(:time1, :time2)
|
172
|
+
Benchmark.should_receive(:measure).twice.and_yield.and_return(:measured_time1, :measured_time2)
|
173
|
+
instance = @klass.new
|
174
|
+
instance.some_method('arg1', 'arg2')
|
175
|
+
instance.another_method
|
176
|
+
instance.benchmark_report.entries.should ==
|
177
|
+
[
|
178
|
+
{:timestamp => :time1, :context =>['context 1 arg1, arg2'], :execution_time => :measured_time1 },
|
179
|
+
{:timestamp => :time2, :context =>['another_method'], :execution_time => :measured_time2 }
|
180
|
+
]
|
181
|
+
end
|
182
|
+
|
183
|
+
describe 'with nested context' do
|
184
|
+
before(:each) do
|
185
|
+
@klass.class_eval do
|
186
|
+
def some_method(*args); 'something'; end
|
187
|
+
def another_method; 'another'; end
|
188
|
+
def yet_another_method; some_method('blah'); 'yet ' + another_method; end
|
189
|
+
def yet_another_yet_another_method; 'yet ' + yet_another_method; end
|
190
|
+
benchmark :another_method => 'another', :some_method => 'some', :yet_another_method => 'yet', :yet_another_yet_another_method => 'yet yet'
|
191
|
+
end
|
192
|
+
|
193
|
+
DateTime.stub!(:now).and_return(*Array.new(9) {|i| "time#{i + 1}".to_sym})
|
194
|
+
Benchmark.should_receive(:measure).twice.and_yield.and_return(*Array.new(9) {|i| "measured_time#{i + 1}".to_sym})
|
195
|
+
@instance = @klass.new
|
196
|
+
@instance.some_method('arg1', 'arg2')
|
197
|
+
@instance.another_method
|
198
|
+
@instance.yet_another_method
|
199
|
+
@instance.yet_another_yet_another_method
|
200
|
+
end
|
201
|
+
|
202
|
+
it 'should benchmark methods without any nesting level' do
|
203
|
+
@instance.benchmark_report.entries.should ==
|
204
|
+
[
|
205
|
+
{:timestamp => :time1, :context =>['some arg1, arg2'], :execution_time => :measured_time1 },
|
206
|
+
{:timestamp => :time2, :context =>['another'], :execution_time => :measured_time2 },
|
207
|
+
{:timestamp => :time3, :context =>['yet'], :execution_time => :measured_time5 },
|
208
|
+
{:timestamp => :time6, :context =>['yet yet'], :execution_time => :measured_time9 },
|
209
|
+
]
|
210
|
+
end
|
211
|
+
|
212
|
+
it 'should benchmark methods till two nesting levels' do
|
213
|
+
@instance.benchmark_report.entries(:nesting_limit => 2).should ==
|
214
|
+
[
|
215
|
+
{:timestamp => :time1, :context =>['some arg1, arg2', '-', '-'], :execution_time => :measured_time1 },
|
216
|
+
{:timestamp => :time2, :context =>['another', '-', '-'], :execution_time => :measured_time2 },
|
217
|
+
{:timestamp => :time3, :context =>['yet', '-', '-'], :execution_time => :measured_time5 },
|
218
|
+
{:timestamp => :time4, :context =>['yet', 'some blah', '-'], :execution_time => :measured_time3 },
|
219
|
+
{:timestamp => :time5, :context =>['yet', 'another', '-'], :execution_time => :measured_time4 },
|
220
|
+
{:timestamp => :time6, :context =>['yet yet', '-', '-'], :execution_time => :measured_time9 },
|
221
|
+
{:timestamp => :time7, :context =>['yet yet', 'yet', '-'], :execution_time => :measured_time8 },
|
222
|
+
{:timestamp => :time8, :context =>['yet yet', 'yet', 'some blah'], :execution_time => :measured_time6 },
|
223
|
+
{:timestamp => :time9, :context =>['yet yet', 'yet', 'another'], :execution_time => :measured_time7 }
|
224
|
+
]
|
225
|
+
end
|
226
|
+
|
227
|
+
it 'should benchmark methods till all nesting levels' do
|
228
|
+
@instance.benchmark_report.entries(:nesting_limit => :none).should ==
|
229
|
+
[
|
230
|
+
{:timestamp => :time1, :context =>['some arg1, arg2', '-', '-'], :execution_time => :measured_time1 },
|
231
|
+
{:timestamp => :time2, :context =>['another', '-', '-'], :execution_time => :measured_time2 },
|
232
|
+
{:timestamp => :time3, :context =>['yet', '-', '-'], :execution_time => :measured_time5 },
|
233
|
+
{:timestamp => :time4, :context =>['yet', 'some blah', '-'], :execution_time => :measured_time3 },
|
234
|
+
{:timestamp => :time5, :context =>['yet', 'another', '-'], :execution_time => :measured_time4 },
|
235
|
+
{:timestamp => :time6, :context =>['yet yet', '-', '-'], :execution_time => :measured_time9 },
|
236
|
+
{:timestamp => :time7, :context =>['yet yet', 'yet', '-'], :execution_time => :measured_time8 },
|
237
|
+
{:timestamp => :time8, :context =>['yet yet', 'yet', 'some blah'], :execution_time => :measured_time6 },
|
238
|
+
{:timestamp => :time9, :context =>['yet yet', 'yet', 'another'], :execution_time => :measured_time7 }
|
239
|
+
]
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
describe 'exporting as csv' do
|
244
|
+
it 'should generate csv output for entries' do
|
245
|
+
@klass.class_eval do
|
246
|
+
def some_method(*args); 'something'; end
|
247
|
+
def another_method; 'another'; end
|
248
|
+
def yet_another_method; some_method('blah'); 'yet ' + another_method; end
|
249
|
+
def yet_another_yet_another_method; 'yet ' + yet_another_method; end
|
250
|
+
benchmark :another_method => 'another', :some_method => 'some', :yet_another_method => 'yet', :yet_another_yet_another_method => 'yet yet'
|
251
|
+
end
|
252
|
+
|
253
|
+
times = (1..5).collect{ |i| DateTime.parse("2009-07-29T10:0#{i}:00+05:30") }
|
254
|
+
DateTime.stub!(:now).and_return(*times)
|
255
|
+
Benchmark.should_receive(:measure).twice.and_yield.and_return(*Array.new(5) {|i| stub("measured_time#{i + 1}", :real => i + 1) })
|
256
|
+
instance = @klass.new
|
257
|
+
instance.some_method('arg1', 'arg2')
|
258
|
+
instance.yet_another_yet_another_method
|
259
|
+
|
260
|
+
instance.benchmark_report.to_csv(:nesting_limit => :none, :starting_context => 'initial context', :csv_options => {:row_sep => "\n"}).should ==
|
261
|
+
<<EOS
|
262
|
+
"2009-07-29T10:01:00+05:30","initial context","some arg1, arg2","-","-","1"
|
263
|
+
"2009-07-29T10:02:00+05:30","initial context","yet yet","-","-","5"
|
264
|
+
"2009-07-29T10:03:00+05:30","initial context","yet yet","yet","-","4"
|
265
|
+
"2009-07-29T10:04:00+05:30","initial context","yet yet","yet","some blah","2"
|
266
|
+
"2009-07-29T10:05:00+05:30","initial context","yet yet","yet","another","3"
|
267
|
+
EOS
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
metadata
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: benchmarkable
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: "1.0"
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Aman King
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-09-14 00:00:00 +05:30
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Benchmarkable allows monitoring the performance of instance methods and reporting those in csv format
|
17
|
+
email: amanking@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
24
|
+
files:
|
25
|
+
- README
|
26
|
+
- lib/benchmarkable.rb
|
27
|
+
- spec/benchmarkable_spec.rb
|
28
|
+
has_rdoc: true
|
29
|
+
homepage: http://bitbucket.org/amanking/benchmarkable/
|
30
|
+
licenses: []
|
31
|
+
|
32
|
+
post_install_message:
|
33
|
+
rdoc_options: []
|
34
|
+
|
35
|
+
require_paths:
|
36
|
+
- lib
|
37
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: "0"
|
42
|
+
version:
|
43
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: "0"
|
48
|
+
version:
|
49
|
+
requirements: []
|
50
|
+
|
51
|
+
rubyforge_project:
|
52
|
+
rubygems_version: 1.3.5
|
53
|
+
signing_key:
|
54
|
+
specification_version: 3
|
55
|
+
summary: Benchmarkable allows monitoring the performance of instance methods and reporting those in csv format
|
56
|
+
test_files:
|
57
|
+
- spec/benchmarkable_spec.rb
|