rubyperf 1.3.5 → 1.3.6

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.3.5
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 = 100
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 ||= measure_overhead
48
- @measurements = {} # A hash of Measure; must repeat here to cleanup what measure_overhead did
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.clone
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
- t -= @@overhead if @subtract_overhead && @@overhead # Factor out the overhead of measure, if we are asked to do so
133
- root.count += m.count if root
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 && @@overhead.total>=0 && @@overhead.real>=0
353
+ over=@@overhead[:time].total+@@overhead[:time].real
354
+ if over>0
322
355
  m=get_measurement(path)
323
- if m.count>0 && (m.time.total+m.time.real)>0
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/cnt
390
+ {:time=>t,:count=>cnt}
351
391
  end
352
392
 
353
393
  def set_measurement(path,m)
@@ -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.time if path.size==2 # This calculates the max of the level-1 entries needed for the root entry.
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
- totals[totals.size-1] = m.time.real
68
- totals[totals.size-1] = MIN_TOTAL_TIME if totals[totals.size-1]<MIN_TOTAL_TIME
69
- percents[what]=(m.time.real*100.0)/totals[totals.size-2]
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 => "accuracy", :max_accuracy => MAX_ACCURACY_SIZE,
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.time,
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
- if accuracy<0
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.5"
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-16}
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 = [
@@ -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,10',
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) >= 0
135
- assert m.accuracy(m.measurements['\blocks\a'].path) >= 0
136
- assert m.accuracy(m.measurements['\blocks\b'].path) < 0
137
- assert_equal 2,m.report_list_of_measures(:filter_below_accuracy=>0.0001).length
138
- assert_equal 2,m.report_list_of_measures(:filter_below_percent=>1).length
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,5',
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,500500',
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
- #assert m_no_overhead.blocks_time.total > m_yes_overhead.blocks_time.total
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
- - 5
8
+ - 6
9
9
  segments_generated: true
10
- version: 1.3.5
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-16 00:00:00 -08:00
18
+ date: 2012-01-17 00:00:00 -08:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency