rubyperf 1.3.5 → 1.3.6
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/VERSION +1 -1
- data/lib/perf/meter.rb +59 -19
- data/lib/perf/report_format.rb +25 -21
- data/rubyperf.gemspec +2 -2
- data/test/test_perf_meter.rb +20 -11
- metadata +3 -3
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.3.
|
1
|
+
1.3.6
|
data/lib/perf/meter.rb
CHANGED
@@ -14,9 +14,22 @@ module Perf
|
|
14
14
|
|
15
15
|
class Meter
|
16
16
|
|
17
|
+
# Constant for accuracy. The constant represents the upper bound of its description.
|
18
|
+
|
19
|
+
ACCURACY_UNKNOWN = 0.0
|
20
|
+
ACCURACY_VERY_POOR = 1.0
|
21
|
+
ACCURACY_POOR = 50.0
|
22
|
+
ACCURACY_FAIR = 100.0
|
23
|
+
ACCURACY_GOOD = 1000.0
|
24
|
+
ACCURACY_EXCELLENT = 1.0/0
|
25
|
+
|
26
|
+
# Name of the path roots
|
27
|
+
|
17
28
|
PATH_MEASURES = '\blocks'
|
18
29
|
PATH_METHODS = '\methods'
|
19
30
|
|
31
|
+
# Hash keys for instrumented methods
|
32
|
+
|
20
33
|
METHOD_TYPE_INSTANCE = :instance
|
21
34
|
METHOD_TYPE_CLASS = :class
|
22
35
|
|
@@ -27,7 +40,7 @@ module Perf
|
|
27
40
|
|
28
41
|
# Overhead calculation tuning constants
|
29
42
|
OVERHEAD_CALC_MAX_REPETITIONS = 1000
|
30
|
-
OVERHEAD_CALC_RUNS =
|
43
|
+
OVERHEAD_CALC_RUNS = 10
|
31
44
|
OVERHEAD_CALC_MIN_TIME = 0.1
|
32
45
|
|
33
46
|
# Creation of a Perf::Meter allows you to specify if you want to consider the overhead in the calculation or not.
|
@@ -41,19 +54,42 @@ module Perf
|
|
41
54
|
@measurements = {} # A hash of Measure
|
42
55
|
@current_path = nil
|
43
56
|
@instrumented_methods = {METHOD_TYPE_INSTANCE=>[],METHOD_TYPE_CLASS=>[]}
|
44
|
-
@class_methods = []
|
45
57
|
@subtract_overhead = @options[:subtract_overhead]
|
46
58
|
if @@overhead.nil?
|
47
|
-
@@overhead
|
48
|
-
@measurements
|
59
|
+
@@overhead = measure_overhead
|
60
|
+
@measurements = {} # A hash of Measure; must repeat here to cleanup what measure_overhead did
|
49
61
|
end
|
50
62
|
end
|
51
63
|
|
52
64
|
def overhead
|
53
65
|
if @subtract_overhead
|
54
|
-
@@overhead.
|
66
|
+
@@overhead.dup
|
55
67
|
else
|
56
|
-
Benchmark::Tms.new
|
68
|
+
{:time=>Benchmark::Tms.new,:count=>0}
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def adjusted_time(m)
|
73
|
+
return m.time if !@subtract_overhead || !@overhead
|
74
|
+
|
75
|
+
utime,stime,cutime,cstime,real = nil,nil,nil,nil,nil
|
76
|
+
|
77
|
+
adj=m.time-((@overhead[:time]*m.count)/@overhead[:count])
|
78
|
+
|
79
|
+
utime = 0.0 if adj.utime < 0.0
|
80
|
+
stime = 0.0 if adj.stime < 0.0
|
81
|
+
cutime = 0.0 if adj.cutime < 0.0
|
82
|
+
cstime = 0.0 if adj.cstime < 0.0
|
83
|
+
real = 0.0 if adj.real < 0.0
|
84
|
+
|
85
|
+
if utime || stime || cutime || cstime || real
|
86
|
+
Benchmark::Tms.new(utime || adj.utime,
|
87
|
+
stime || adj.stime,
|
88
|
+
cutime || adj.cutime,
|
89
|
+
cstime || adj.cstime,
|
90
|
+
real || adj.real)
|
91
|
+
else
|
92
|
+
adj
|
57
93
|
end
|
58
94
|
end
|
59
95
|
|
@@ -124,17 +160,14 @@ module Perf
|
|
124
160
|
begin
|
125
161
|
m=get_measurement(@current_path)
|
126
162
|
m.count += 1
|
163
|
+
root.count += 1 if root
|
127
164
|
m.measuring +=1
|
128
165
|
if m.measuring>1
|
129
166
|
res=code.call
|
130
167
|
else
|
131
168
|
t = Benchmark.measure { res=code.call }
|
132
|
-
|
133
|
-
|
134
|
-
if t.total>=0 || t.real>=0
|
135
|
-
m.time += t
|
136
|
-
root.time += t if root
|
137
|
-
end
|
169
|
+
root.time += t if root
|
170
|
+
m.time += t
|
138
171
|
end
|
139
172
|
ensure
|
140
173
|
@current_path=current_path
|
@@ -317,15 +350,22 @@ module Perf
|
|
317
350
|
|
318
351
|
def accuracy(path)
|
319
352
|
if @@overhead
|
320
|
-
over=@@overhead.total+@@overhead.real
|
321
|
-
if over>0
|
353
|
+
over=@@overhead[:time].total+@@overhead[:time].real
|
354
|
+
if over>0
|
322
355
|
m=get_measurement(path)
|
323
|
-
|
324
|
-
return (m.time.total+m.time.real) / (over*m.count)
|
325
|
-
end
|
356
|
+
return ((m.time.total+m.time.real)*@@overhead[:count] / (over*m.count)) if m.count>0
|
326
357
|
end
|
327
358
|
end
|
328
|
-
-1
|
359
|
+
-1.0
|
360
|
+
end
|
361
|
+
|
362
|
+
# The overhead cannot be larger that any of the measures taken. If a measure taken is larger than the overhead,
|
363
|
+
# than this function takes care of adjusting the overhead. This is called by the ReportFormat class just before
|
364
|
+
# rendering the report, so you should not have to call this by hand unless you are interested in getting the
|
365
|
+
# overhead.
|
366
|
+
|
367
|
+
def adjust_overhead
|
368
|
+
false
|
329
369
|
end
|
330
370
|
|
331
371
|
protected
|
@@ -347,7 +387,7 @@ protected
|
|
347
387
|
cnt += runs # Count the total runs
|
348
388
|
runs *= 2 # Increases the number of runs to quickly adapt to the speed of the machine
|
349
389
|
end
|
350
|
-
t
|
390
|
+
{:time=>t,:count=>cnt}
|
351
391
|
end
|
352
392
|
|
353
393
|
def set_measurement(path,m)
|
data/lib/perf/report_format.rb
CHANGED
@@ -13,8 +13,20 @@ module Perf
|
|
13
13
|
#
|
14
14
|
class ReportFormat
|
15
15
|
|
16
|
+
# Descrition of the accuracy, as reported by the reports
|
17
|
+
|
18
|
+
ACCURACY_DESCRIPTION = {Perf::Meter::ACCURACY_UNKNOWN => "?",
|
19
|
+
Perf::Meter::ACCURACY_VERY_POOR => "very poor",
|
20
|
+
Perf::Meter::ACCURACY_POOR => "poor",
|
21
|
+
Perf::Meter::ACCURACY_FAIR => "fair",
|
22
|
+
Perf::Meter::ACCURACY_GOOD => "good",
|
23
|
+
Perf::Meter::ACCURACY_EXCELLENT => "excellent"}
|
24
|
+
|
25
|
+
# Largest accuracy description length
|
26
|
+
MAX_ACCURACY_SIZE = ACCURACY_DESCRIPTION.values.map{|x| x.length}.max+1 # Maximium size of the accuracy value returned by format_accuracy
|
27
|
+
|
28
|
+
# Minimum possible time
|
16
29
|
MIN_TOTAL_TIME = 1.0e-10
|
17
|
-
MAX_ACCURACY_SIZE = 10
|
18
30
|
|
19
31
|
# Format takes a Perf::Meter plus a hash of options and converts it into a header, followed by a series
|
20
32
|
# of entries in a hash format that can be easily converted in any other format such as Text, HTML, XML, etc.
|
@@ -29,6 +41,9 @@ module Perf
|
|
29
41
|
#
|
30
42
|
|
31
43
|
def format(perf,options={})
|
44
|
+
|
45
|
+
perf.adjust_overhead
|
46
|
+
|
32
47
|
options||={}
|
33
48
|
options[:max_count_len] ||= 6
|
34
49
|
options[:filter_below_accuracy] ||= nil
|
@@ -48,10 +63,10 @@ module Perf
|
|
48
63
|
max_title = title_len if title_len>max_title
|
49
64
|
max_count = m.count.to_s.length if m.count.to_s.length>max_count
|
50
65
|
|
51
|
-
total += m
|
66
|
+
total += perf.adjusted_time(m) if path.size==2 # This calculates the max of the level-1 entries needed for the root entry.
|
52
67
|
end
|
53
68
|
|
54
|
-
totals=[total.real]
|
69
|
+
totals=[total.real+total.total]
|
55
70
|
depth=1
|
56
71
|
keys_in_order.each do |what|
|
57
72
|
m = perf.measurements[what]
|
@@ -64,9 +79,10 @@ module Perf
|
|
64
79
|
end
|
65
80
|
depth=path.size-1
|
66
81
|
end
|
67
|
-
|
68
|
-
totals[totals.size-1] =
|
69
|
-
|
82
|
+
adj=perf.adjusted_time(m)
|
83
|
+
totals[totals.size-1] = adj.real+adj.total
|
84
|
+
#totals[totals.size-1] = MIN_TOTAL_TIME if totals[totals.size-1]<MIN_TOTAL_TIME
|
85
|
+
percents[what]=((adj.real+adj.total)*100.0)/totals[totals.size-2]
|
70
86
|
end
|
71
87
|
|
72
88
|
# Header
|
@@ -74,7 +90,7 @@ module Perf
|
|
74
90
|
:percent => "percent",
|
75
91
|
:count => "count", :max_count => max_count,
|
76
92
|
:time => Benchmark::Tms::CAPTION,
|
77
|
-
:accuracy
|
93
|
+
:accuracy => "accuracy", :max_accuracy => MAX_ACCURACY_SIZE,
|
78
94
|
:options => options)
|
79
95
|
|
80
96
|
# Root
|
@@ -89,7 +105,7 @@ module Perf
|
|
89
105
|
rep << format_measure(:title => title, :max_title => max_title,
|
90
106
|
:percent => percents[what]||0.0,
|
91
107
|
:count => m.count, :max_count => max_count,
|
92
|
-
:time => m
|
108
|
+
:time => perf.adjusted_time(m),
|
93
109
|
:accuracy => format_accuracy(accuracy), :max_accuracy => MAX_ACCURACY_SIZE,
|
94
110
|
:options => options)
|
95
111
|
end
|
@@ -143,19 +159,7 @@ module Perf
|
|
143
159
|
# See Perf::Meter#accuracy for more information
|
144
160
|
|
145
161
|
def format_accuracy(accuracy)
|
146
|
-
|
147
|
-
"unknown"
|
148
|
-
elsif accuracy<=1
|
149
|
-
"very poor"
|
150
|
-
elsif accuracy<=50
|
151
|
-
"poor"
|
152
|
-
elsif accuracy<=100
|
153
|
-
"fair"
|
154
|
-
elsif accuracy<=1000
|
155
|
-
"good"
|
156
|
-
else
|
157
|
-
"excellent"
|
158
|
-
end
|
162
|
+
ACCURACY_DESCRIPTION[ACCURACY_DESCRIPTION.keys.sort.find{|a| a>=accuracy}]
|
159
163
|
end
|
160
164
|
|
161
165
|
end
|
data/rubyperf.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{rubyperf}
|
8
|
-
s.version = "1.3.
|
8
|
+
s.version = "1.3.6"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["lpasqualis"]
|
12
|
-
s.date = %q{2012-01-
|
12
|
+
s.date = %q{2012-01-17}
|
13
13
|
s.description = %q{Used to easily measure the performance of blocks of Ruby code, expressions and methods; provides reporting in various formats}
|
14
14
|
s.email = %q{lpasqualis@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
data/test/test_perf_meter.rb
CHANGED
@@ -66,7 +66,7 @@ class TestPerfMeter < Test::Unit::TestCase
|
|
66
66
|
Array.new(1000000,"abc").reverse.sort
|
67
67
|
end
|
68
68
|
|
69
|
-
assert_equal ['\blocks,
|
69
|
+
assert_equal ['\blocks,9',
|
70
70
|
'\blocks\empty,1',
|
71
71
|
'\blocks\emtpy_loop,1',
|
72
72
|
'\blocks\rough_overhead_x10000,1',
|
@@ -131,12 +131,11 @@ class TestPerfMeter < Test::Unit::TestCase
|
|
131
131
|
m.measure(:a) do
|
132
132
|
("123"*1_000_000).reverse
|
133
133
|
end
|
134
|
-
assert m.accuracy(m.measurements['\blocks'].path)
|
135
|
-
assert m.accuracy(m.measurements['\blocks\a'].path)
|
136
|
-
assert m.accuracy(m.measurements['\blocks\b'].path) <
|
137
|
-
assert_equal 2,m.report_list_of_measures(:filter_below_accuracy=>
|
138
|
-
assert_equal
|
139
|
-
assert_equal 3,m.report_list_of_measures(:filter_below_accuracy=>-10).length
|
134
|
+
assert m.accuracy(m.measurements['\blocks'].path) > Perf::Meter::ACCURACY_UNKNOWN
|
135
|
+
assert m.accuracy(m.measurements['\blocks\a'].path) > Perf::Meter::ACCURACY_UNKNOWN
|
136
|
+
assert m.accuracy(m.measurements['\blocks\b'].path) < Perf::Meter::ACCURACY_VERY_POOR
|
137
|
+
assert_equal 2,m.report_list_of_measures(:filter_below_accuracy=>1).length
|
138
|
+
assert_equal 3,m.report_list_of_measures(:filter_below_accuracy=>Perf::Meter::ACCURACY_UNKNOWN).length
|
140
139
|
assert_equal 3,m.report_list_of_measures(:filter_below_percent=>-10).length
|
141
140
|
end
|
142
141
|
|
@@ -151,8 +150,8 @@ class TestPerfMeter < Test::Unit::TestCase
|
|
151
150
|
m.measure(:c) do
|
152
151
|
sleep(0.0001)
|
153
152
|
end
|
153
|
+
#puts m.report_simple
|
154
154
|
assert_equal 4,m.report_list_of_measures.length
|
155
|
-
assert_equal 3,m.report_list_of_measures(:filter_below_accuracy=>1).length
|
156
155
|
assert_equal 3,m.report_list_of_measures(:filter_below_accuracy=>500).length
|
157
156
|
assert_equal 3,m.report_list_of_measures(:filter_below_percent=>10).length
|
158
157
|
assert_equal 2,m.report_list_of_measures(:filter_below_percent=>45).length
|
@@ -299,13 +298,21 @@ class TestPerfMeter < Test::Unit::TestCase
|
|
299
298
|
'\blocks\some_expressions\expression1 = "1111",1',
|
300
299
|
'\blocks\some_expressions\expression1 = "13579",1',
|
301
300
|
'\blocks\some_expressions\expression2 = "string",1',
|
302
|
-
'\methods,
|
301
|
+
'\methods,4',
|
303
302
|
'\methods\#<Class:PerfTestExample>.static_method,1',
|
304
303
|
'\methods\PerfTestExample.test,1',
|
305
304
|
'\methods\PerfTestExample.test_np,2'],
|
306
305
|
m.report_list_of_measures
|
307
306
|
end
|
308
307
|
|
308
|
+
def test_precision
|
309
|
+
runs=1_000
|
310
|
+
a=(1..100_000).to_a
|
311
|
+
m=Perf::Meter.new
|
312
|
+
runs.times { m.measure(:a) { a.reverse! } }
|
313
|
+
m.measure(:b) { runs.times { a.reverse! } }
|
314
|
+
# TODO find proper assert
|
315
|
+
end
|
309
316
|
|
310
317
|
def test_overhead
|
311
318
|
runs=1_000
|
@@ -319,7 +326,7 @@ class TestPerfMeter < Test::Unit::TestCase
|
|
319
326
|
b2_yes_overhead=Benchmark.measure { runs.times { a.reverse! } }
|
320
327
|
|
321
328
|
|
322
|
-
assert_equal ['\blocks,
|
329
|
+
assert_equal ['\blocks,1000',
|
323
330
|
'\blocks\a,1000'],
|
324
331
|
m_no_overhead.report_list_of_measures
|
325
332
|
|
@@ -338,6 +345,8 @@ class TestPerfMeter < Test::Unit::TestCase
|
|
338
345
|
#puts m_no_overhead.report_simple
|
339
346
|
#puts m_yes_overhead.report_simple
|
340
347
|
#
|
341
|
-
#
|
348
|
+
# puts m_no_overhead.blocks_time
|
349
|
+
# puts m_yes_overhead.blocks_time
|
350
|
+
# assert m_no_overhead.blocks_time.total+m_no_overhead.blocks_time.real <= m_yes_overhead.blocks_time.total+m_no_overhead.blocks_time.real
|
342
351
|
end
|
343
352
|
end
|
metadata
CHANGED
@@ -5,9 +5,9 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 1
|
7
7
|
- 3
|
8
|
-
-
|
8
|
+
- 6
|
9
9
|
segments_generated: true
|
10
|
-
version: 1.3.
|
10
|
+
version: 1.3.6
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- lpasqualis
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-01-
|
18
|
+
date: 2012-01-17 00:00:00 -08:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|