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 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