hitimes 1.0.4-x86-mswin32
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/HISTORY +60 -0
- data/LICENSE +13 -0
- data/README +134 -0
- data/Rakefile +66 -0
- data/examples/benchmarks.rb +113 -0
- data/examples/stats.rb +31 -0
- data/ext/hitimes/extconf.rb +17 -0
- data/ext/hitimes/hitimes_ext.c +21 -0
- data/ext/hitimes/hitimes_instant_clock_gettime.c +28 -0
- data/ext/hitimes/hitimes_instant_osx.c +16 -0
- data/ext/hitimes/hitimes_instant_windows.c +27 -0
- data/ext/hitimes/hitimes_interval.c +362 -0
- data/ext/hitimes/hitimes_interval.h +73 -0
- data/ext/hitimes/hitimes_stats.c +269 -0
- data/ext/hitimes/hitimes_stats.h +30 -0
- data/gemspec.rb +60 -0
- data/lib/hitimes.rb +31 -0
- data/lib/hitimes/1.8/hitimes_ext.so +0 -0
- data/lib/hitimes/1.9/hitimes_ext.so +0 -0
- data/lib/hitimes/metric.rb +112 -0
- data/lib/hitimes/mutexed_stats.rb +28 -0
- data/lib/hitimes/paths.rb +53 -0
- data/lib/hitimes/stats.rb +54 -0
- data/lib/hitimes/timed_metric.rb +177 -0
- data/lib/hitimes/timed_value_metric.rb +235 -0
- data/lib/hitimes/value_metric.rb +72 -0
- data/lib/hitimes/version.rb +57 -0
- data/spec/interval_spec.rb +133 -0
- data/spec/metric_spec.rb +30 -0
- data/spec/mutex_stats_spec.rb +34 -0
- data/spec/paths_spec.rb +13 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/stats_spec.rb +100 -0
- data/spec/timed_metric_spec.rb +155 -0
- data/spec/timed_value_metric_spec.rb +172 -0
- data/spec/value_metric_spec.rb +110 -0
- data/spec/version_spec.rb +33 -0
- data/tasks/announce.rake +42 -0
- data/tasks/config.rb +108 -0
- data/tasks/distribution.rake +77 -0
- data/tasks/documentation.rake +32 -0
- data/tasks/extension.rake +92 -0
- data/tasks/rspec.rake +31 -0
- data/tasks/rubyforge.rake +55 -0
- data/tasks/utils.rb +80 -0
- metadata +150 -0
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'hitimes'
|
2
|
+
require 'thread'
|
3
|
+
|
4
|
+
module Hitimes
|
5
|
+
#
|
6
|
+
# MutexedStats is the start of a threadsafe Stats class. Currently, on MRI
|
7
|
+
# Ruby the Stats object is already threadsafe, so there is no need to use
|
8
|
+
# MutexedStats.
|
9
|
+
#
|
10
|
+
class MutexedStats < Stats
|
11
|
+
def initialize
|
12
|
+
@mutex = Mutex.new
|
13
|
+
end
|
14
|
+
|
15
|
+
# call-seq:
|
16
|
+
# mutex_stat.update( val ) -> nil
|
17
|
+
#
|
18
|
+
# Update the running stats with the new value in a threadsafe manner.
|
19
|
+
#
|
20
|
+
def update( value )
|
21
|
+
@mutex.synchronize do
|
22
|
+
super( value )
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
@@ -0,0 +1,53 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2008 Jeremy Hinegardner
|
3
|
+
# All rights reserved. See LICENSE and/or COPYING for details.
|
4
|
+
#++
|
5
|
+
#
|
6
|
+
module Hitimes
|
7
|
+
#
|
8
|
+
# Access to various paths inside the project programatically
|
9
|
+
#
|
10
|
+
module Paths
|
11
|
+
#
|
12
|
+
# :call-seq:
|
13
|
+
# Hitimes::Paths.root_dir -> String
|
14
|
+
#
|
15
|
+
# Returns The full expanded path of the parent directory of +lib+
|
16
|
+
# going up the path from the current file. A trailing File::SEPARATOR
|
17
|
+
# is guaranteed.
|
18
|
+
#
|
19
|
+
def self.root_dir
|
20
|
+
@root_dir ||=(
|
21
|
+
path_parts = ::File.expand_path(__FILE__).split(::File::SEPARATOR)
|
22
|
+
lib_index = path_parts.rindex("lib")
|
23
|
+
@root_dir = path_parts[0...lib_index].join(::File::SEPARATOR) + ::File::SEPARATOR
|
24
|
+
)
|
25
|
+
end
|
26
|
+
|
27
|
+
#
|
28
|
+
# :call-seq:
|
29
|
+
# Hitimes::Paths.lib_path( *args ) -> String
|
30
|
+
#
|
31
|
+
# Returns The full expanded path of the +lib+ directory below
|
32
|
+
# _root_dir_. All parameters passed in are joined onto the
|
33
|
+
# result. A trailing File::SEPARATOR is guaranteed if
|
34
|
+
# _args_ are *not* present.
|
35
|
+
#
|
36
|
+
def self.lib_path(*args)
|
37
|
+
self.sub_path("lib", *args)
|
38
|
+
end
|
39
|
+
|
40
|
+
#
|
41
|
+
# :call-seq:
|
42
|
+
# Hitimes::Paths.sub_path( sub, *args ) -> String
|
43
|
+
#
|
44
|
+
# Returns the full expanded path of the +sub+ directory below _root_dir. All
|
45
|
+
# _arg_ parameters passed in are joined onto the result. A trailing
|
46
|
+
# File::SEPARATOR is guaranteed if _args_ are *not* present.
|
47
|
+
#
|
48
|
+
def self.sub_path(sub,*args)
|
49
|
+
sp = ::File.join(root_dir, sub) + File::SEPARATOR
|
50
|
+
sp = ::File.join(sp, *args) if args
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'hitimes'
|
2
|
+
require 'stringio'
|
3
|
+
module Hitimes
|
4
|
+
class Stats
|
5
|
+
# A list of the available stats
|
6
|
+
STATS = %w[ count max mean min rate stddev sum sumsq ]
|
7
|
+
|
8
|
+
#
|
9
|
+
# call-seq:
|
10
|
+
# stat.to_hash -> Hash
|
11
|
+
# stat.to_hash( %w[ count max mean ]) -> Hash
|
12
|
+
#
|
13
|
+
# return a hash of the stats. By default this returns a hash of all stats
|
14
|
+
# but passing in an array of items will limit the stats returned to only
|
15
|
+
# those in the Array.
|
16
|
+
#
|
17
|
+
# If passed in an empty array or nil to to_hash then STATS is assumed to be
|
18
|
+
# the list of stats to return in the hash.
|
19
|
+
#
|
20
|
+
def to_hash( *args )
|
21
|
+
h = {}
|
22
|
+
args = [ args ].flatten
|
23
|
+
args = STATS if args.empty?
|
24
|
+
args.each do |meth|
|
25
|
+
h[meth] = self.send( meth )
|
26
|
+
end
|
27
|
+
return h
|
28
|
+
end
|
29
|
+
|
30
|
+
#
|
31
|
+
# call-seq:
|
32
|
+
# stat.to_json -> String
|
33
|
+
# stat.to_json( *args ) -> String
|
34
|
+
#
|
35
|
+
# return a json string of the stats. By default this returns a json string
|
36
|
+
# of all the stats. If an array of items is passed in, those that match the
|
37
|
+
# known stats will be all that is included in the json output.
|
38
|
+
#
|
39
|
+
def to_json( *args )
|
40
|
+
h = to_hash( *args )
|
41
|
+
a = []
|
42
|
+
s = StringIO.new
|
43
|
+
|
44
|
+
s.print "{ "
|
45
|
+
h.each_pair do |k,v|
|
46
|
+
a << "\"#{k}\": #{v}"
|
47
|
+
end
|
48
|
+
s.print a.join(", ")
|
49
|
+
s.print "}"
|
50
|
+
return s.string
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,177 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2008, 2009 Jeremy Hinegardner
|
3
|
+
# All rights reserved. See LICENSE and/or COPYING for details.
|
4
|
+
#++
|
5
|
+
|
6
|
+
require 'hitimes'
|
7
|
+
require 'forwardable'
|
8
|
+
module Hitimes
|
9
|
+
#
|
10
|
+
# A TimedMetric holds the metrics on how long it takes to do something. For
|
11
|
+
# example, measuring how long a method takes to operate.
|
12
|
+
#
|
13
|
+
# tm = TimedMetric.new( 'my-method' )
|
14
|
+
#
|
15
|
+
# 200.times do
|
16
|
+
# my_method_result = tm.measure do
|
17
|
+
# my_method( ... )
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# puts "#{ tm.name } operated at a rate of #{ tm.rate } calls per second"
|
22
|
+
#
|
23
|
+
# Since TimedMetric is a child class of Metric make sure to look at the
|
24
|
+
# Metric API also.
|
25
|
+
#
|
26
|
+
# A TimedMetric measures the execution time of an option with the Interval
|
27
|
+
# class.
|
28
|
+
#
|
29
|
+
# A TimedMetric contains a Stats object, therefore TimedMetric has +count+, +max+,
|
30
|
+
# +mean+, +min+, +rate+, +stddev+, +sum+, +sumsq+ methods that delegate to that Stats
|
31
|
+
# object for convenience.
|
32
|
+
#
|
33
|
+
#
|
34
|
+
class TimedMetric < Metric
|
35
|
+
# holds all the statistics
|
36
|
+
attr_reader :stats
|
37
|
+
|
38
|
+
class << TimedMetric
|
39
|
+
#
|
40
|
+
# :call-seq:
|
41
|
+
# TimedMetric.now -> TimedMetric
|
42
|
+
#
|
43
|
+
# Return a TimedMetric that has been started
|
44
|
+
#
|
45
|
+
def now( name, additional_data = {} )
|
46
|
+
t = TimedMetric.new( name, additional_data )
|
47
|
+
t.start
|
48
|
+
return t
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
#
|
53
|
+
# :call-seq:
|
54
|
+
# TimedMetric.new( 'name') -> TimedMetric
|
55
|
+
# TimedMetric.new( 'name', 'other' => 'data') -> TimedMetric
|
56
|
+
#
|
57
|
+
# Create a new TimedMetric giving it a name and additional data.
|
58
|
+
# +additional_data+ may be anything that follows the +to_hash+ protocol
|
59
|
+
#
|
60
|
+
def initialize( name, additional_data = {} )
|
61
|
+
super( name, additional_data )
|
62
|
+
@stats = Stats.new
|
63
|
+
@current_interval = Interval.new
|
64
|
+
end
|
65
|
+
|
66
|
+
#
|
67
|
+
# :call-seq:
|
68
|
+
# timed_metric.running? -> true or false
|
69
|
+
#
|
70
|
+
# return whether or not the timer is currently running.
|
71
|
+
#
|
72
|
+
def running?
|
73
|
+
@current_interval.running?
|
74
|
+
end
|
75
|
+
|
76
|
+
#
|
77
|
+
# :call-seq:
|
78
|
+
# timed_metric.start -> nil
|
79
|
+
#
|
80
|
+
# Start the current metric, if the current metric is already started, then
|
81
|
+
# this is a noop.
|
82
|
+
#
|
83
|
+
def start
|
84
|
+
if not @current_interval.running? then
|
85
|
+
@current_interval.start
|
86
|
+
@sampling_start_time ||= self.utc_microseconds()
|
87
|
+
@sampling_start_interval ||= Interval.now
|
88
|
+
end
|
89
|
+
nil
|
90
|
+
end
|
91
|
+
|
92
|
+
#
|
93
|
+
# :call-seq:
|
94
|
+
# timed_metric.stop -> Float or nil
|
95
|
+
#
|
96
|
+
# Stop the current metric. This updates the stats and removes the current
|
97
|
+
# interval. If the timer was stopped then the duration of the last Interval
|
98
|
+
# is returned. If the timer was already stopped then false is returned and
|
99
|
+
# no stats are updated.
|
100
|
+
#
|
101
|
+
def stop
|
102
|
+
if @current_interval.running? then
|
103
|
+
d = @current_interval.stop
|
104
|
+
@stats.update( d )
|
105
|
+
@current_interval = Interval.new
|
106
|
+
|
107
|
+
# update the length of time we have been sampling
|
108
|
+
@sampling_delta = @sampling_start_interval.duration_so_far
|
109
|
+
|
110
|
+
return d
|
111
|
+
end
|
112
|
+
return false
|
113
|
+
end
|
114
|
+
|
115
|
+
#
|
116
|
+
# :call-seq:
|
117
|
+
# timed_metric.measure { ... } -> Object
|
118
|
+
#
|
119
|
+
# Measure the execution of a block and add those stats to the running stats.
|
120
|
+
# The return value is the return value of the block
|
121
|
+
#
|
122
|
+
def measure( &block )
|
123
|
+
return_value = nil
|
124
|
+
begin
|
125
|
+
start
|
126
|
+
return_value = yield
|
127
|
+
ensure
|
128
|
+
stop
|
129
|
+
end
|
130
|
+
return return_value
|
131
|
+
end
|
132
|
+
|
133
|
+
#
|
134
|
+
# :call-seq:
|
135
|
+
# timed_metric.split -> Float
|
136
|
+
#
|
137
|
+
# Split the current TimedMetric. Essentially, mark a split time. This means
|
138
|
+
# stop the current interval and create a new interval, but make sure
|
139
|
+
# that the new interval lines up exactly, timewise, behind the previous
|
140
|
+
# interval.
|
141
|
+
#
|
142
|
+
# If the timer is running, then split returns the duration of the previous
|
143
|
+
# interval, i.e. the split-time. If the timer is not running, nothing
|
144
|
+
# happens and false is returned.
|
145
|
+
#
|
146
|
+
def split
|
147
|
+
if @current_interval.running? then
|
148
|
+
next_interval = @current_interval.split
|
149
|
+
d = @current_interval.duration
|
150
|
+
@stats.update( d )
|
151
|
+
@current_interval = next_interval
|
152
|
+
return d
|
153
|
+
end
|
154
|
+
return false
|
155
|
+
end
|
156
|
+
|
157
|
+
#
|
158
|
+
# :call-seq:
|
159
|
+
# metric.to_hash -> Hash
|
160
|
+
#
|
161
|
+
# Convert the metric to a hash
|
162
|
+
#
|
163
|
+
def to_hash
|
164
|
+
h = super
|
165
|
+
Stats::STATS.each do |s|
|
166
|
+
h[s] = self.send( s )
|
167
|
+
end
|
168
|
+
return h
|
169
|
+
end
|
170
|
+
|
171
|
+
|
172
|
+
# forward appropriate calls directly to the stats object
|
173
|
+
extend Forwardable
|
174
|
+
def_delegators :@stats, :count, :sum, :max, :mean, :min, :rate, :stddev, :sum, :sumsq
|
175
|
+
alias :duration :sum
|
176
|
+
end
|
177
|
+
end
|
@@ -0,0 +1,235 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2008, 2009 Jeremy Hinegardner
|
3
|
+
# All rights reserved. See LICENSE and/or COPYING for details.
|
4
|
+
#++
|
5
|
+
|
6
|
+
require 'hitimes'
|
7
|
+
|
8
|
+
module Hitimes
|
9
|
+
#
|
10
|
+
# A TimedValueMetric holds the metrics on how long it takes to do a batch of something.
|
11
|
+
# something. For measuring how long a method takes to operate on N items.
|
12
|
+
#
|
13
|
+
# tm = TimedValueMetric.new( 'my-batch-method' )
|
14
|
+
#
|
15
|
+
# 42.times do
|
16
|
+
# tm.start
|
17
|
+
# number_of_items_processed = do_something
|
18
|
+
# tm.stop( number_of_items_processed )
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# puts "#{ tm.name } operated at a rate of #{ tm.rate } calls per second"
|
22
|
+
#
|
23
|
+
# TimedValueMetric combines the usefulness of a ValueMetric and a TimedMetric.
|
24
|
+
# The stats are available for both the time it took to do the operation and
|
25
|
+
# the sizes of the batches that were run.
|
26
|
+
#
|
27
|
+
# A TimedValueMetric keeps track of both the time it took to do an operation
|
28
|
+
# and the size of the batch that was operated on. These metrics are kept
|
29
|
+
# separately as +timed_stats+ and +value_stats+ accessors.
|
30
|
+
#
|
31
|
+
class TimedValueMetric < Metric
|
32
|
+
# holds all the Timed statistics
|
33
|
+
attr_reader :timed_stats
|
34
|
+
|
35
|
+
# holds all the Value statistics
|
36
|
+
attr_reader :value_stats
|
37
|
+
|
38
|
+
class << TimedValueMetric
|
39
|
+
#
|
40
|
+
# :call-seq:
|
41
|
+
# TimedValueMetric.now( 'name' ) -> TimedValueMetric
|
42
|
+
#
|
43
|
+
# Return a TimedValueMetric that has been started
|
44
|
+
#
|
45
|
+
def now( name, additional_data = {} )
|
46
|
+
t = TimedValueMetric.new( name, additional_data )
|
47
|
+
t.start
|
48
|
+
return t
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
#
|
53
|
+
# :call-seq:
|
54
|
+
# TimedValueMetric.new( 'name') -> TimedValueMetric
|
55
|
+
# TimedValueMetric.new( 'name', 'other' => 'data') -> TimedValueMetric
|
56
|
+
#
|
57
|
+
# Create a new TimedValueMetric giving it a name and additional data.
|
58
|
+
# +additional_data+ may be anything that follows the +to_hash+ protocol
|
59
|
+
#
|
60
|
+
def initialize( name, additional_data = {} )
|
61
|
+
super( name, additional_data )
|
62
|
+
@timed_stats = Stats.new
|
63
|
+
@value_stats = Stats.new
|
64
|
+
@current_interval = Interval.new
|
65
|
+
end
|
66
|
+
|
67
|
+
#
|
68
|
+
# :call-seq:
|
69
|
+
# timed_value_metric.running? -> true or false
|
70
|
+
#
|
71
|
+
# return whether or not the metric is currently timing something.
|
72
|
+
#
|
73
|
+
def running?
|
74
|
+
@current_interval.running?
|
75
|
+
end
|
76
|
+
|
77
|
+
#
|
78
|
+
# :call-seq:
|
79
|
+
# timed_value_metric.start -> nil
|
80
|
+
#
|
81
|
+
# Start the current timer, if the current timer is already started, then
|
82
|
+
# this is a noop.
|
83
|
+
#
|
84
|
+
def start
|
85
|
+
if not @current_interval.running? then
|
86
|
+
@current_interval.start
|
87
|
+
@sampling_start_time ||= self.utc_microseconds()
|
88
|
+
@sampling_start_interval ||= Interval.now
|
89
|
+
end
|
90
|
+
nil
|
91
|
+
end
|
92
|
+
|
93
|
+
#
|
94
|
+
# :call-seq:
|
95
|
+
# timed_value_metric.stop( count ) -> Float or nil
|
96
|
+
#
|
97
|
+
# Stop the current metric. The +count+ parameter must be a
|
98
|
+
# value to update to the _value_ portion of the TimedValueMetric. Generally
|
99
|
+
# this is probably the number of things that were operated upon since
|
100
|
+
# +start+ was invoked.
|
101
|
+
#
|
102
|
+
# This updates both the +value_stats+ and +timed_stats+ stats and removes
|
103
|
+
# the current interval. If the metric is stopped then the duration of the
|
104
|
+
# last Interval is returned. If the metric was already stopped before this
|
105
|
+
# call, then false is returned and no stats are updated.
|
106
|
+
#
|
107
|
+
#
|
108
|
+
def stop( value )
|
109
|
+
if @current_interval.running? then
|
110
|
+
d = @current_interval.stop
|
111
|
+
@timed_stats.update( d )
|
112
|
+
@current_interval = Interval.new
|
113
|
+
@value_stats.update( value )
|
114
|
+
|
115
|
+
# update the lenght of time we have been sampling
|
116
|
+
@sampling_delta = @sampling_start_interval.duration_so_far
|
117
|
+
|
118
|
+
return d
|
119
|
+
end
|
120
|
+
return false
|
121
|
+
end
|
122
|
+
|
123
|
+
#
|
124
|
+
# :call-seq:
|
125
|
+
# timed_value_metric.measure( value ) { ... } -> Object
|
126
|
+
#
|
127
|
+
# Measure the execution of a block and add those stats to the running stats.
|
128
|
+
# The return value is the return value of the block. A value must be passed
|
129
|
+
# into +measure+ to update the +value_stats+ portion of the TimedValueMetric.
|
130
|
+
#
|
131
|
+
def measure( value, &block )
|
132
|
+
return_value = nil
|
133
|
+
begin
|
134
|
+
start
|
135
|
+
return_value = yield
|
136
|
+
ensure
|
137
|
+
stop( value )
|
138
|
+
end
|
139
|
+
return return_value
|
140
|
+
end
|
141
|
+
|
142
|
+
#
|
143
|
+
# :call-seq:
|
144
|
+
# timed_value_metric.split( value ) -> Float
|
145
|
+
#
|
146
|
+
# Split the current metric. Essentially, mark a split time. This means
|
147
|
+
# stop the current interval, with the givein +value+ and create a new
|
148
|
+
# interval, but make sure that the new interval lines up exactly, timewise,
|
149
|
+
# behind the previous interval.
|
150
|
+
#
|
151
|
+
# If the metric is running, then split returns the duration of the previous
|
152
|
+
# interval, i.e. the split-time. If the metric is not running, nothing
|
153
|
+
# happens, no stats are updated, and false is returned.
|
154
|
+
#
|
155
|
+
#
|
156
|
+
def split( value )
|
157
|
+
if @current_interval.running? then
|
158
|
+
next_interval = @current_interval.split
|
159
|
+
d = @current_interval.duration
|
160
|
+
@timed_stats.update( d )
|
161
|
+
@value_stats.update( value )
|
162
|
+
@current_interval = next_interval
|
163
|
+
return d
|
164
|
+
end
|
165
|
+
return false
|
166
|
+
end
|
167
|
+
|
168
|
+
#
|
169
|
+
# :call-seq:
|
170
|
+
# timed_value_metric.duration -> Float
|
171
|
+
#
|
172
|
+
# The duration of measured time from the metric.
|
173
|
+
#
|
174
|
+
def duration
|
175
|
+
@timed_stats.sum
|
176
|
+
end
|
177
|
+
|
178
|
+
#
|
179
|
+
# :call-seq:
|
180
|
+
# timed_value_metric.unit_count -> Float
|
181
|
+
#
|
182
|
+
# The sum of all values passed to +stop+ or +skip+ or +measure+
|
183
|
+
#
|
184
|
+
def unit_count
|
185
|
+
@value_stats.sum
|
186
|
+
end
|
187
|
+
|
188
|
+
#
|
189
|
+
# :call-seq:
|
190
|
+
# timed_value_metric.rate -> Float
|
191
|
+
#
|
192
|
+
# Rate in the context of the TimedValueMetric is different than the
|
193
|
+
# TimedMetric. In the TimedValueMetric, each measurement of time is
|
194
|
+
# associated with a quantity of things done during that unit of time. So
|
195
|
+
# the +rate+ for a TimedValueMetric is the (sum of all quantities sampled) /
|
196
|
+
# ( sum of all durations measured )
|
197
|
+
#
|
198
|
+
# For example, say you were measuring, using a TimedValueMetric batch jobs
|
199
|
+
# that had individual units of work.
|
200
|
+
#
|
201
|
+
# tvm = TimedValueMetric.new( 'some-batch' )
|
202
|
+
# tvm.start
|
203
|
+
# # process a batch of 12 units
|
204
|
+
# duration1 = tvm.stop( 12 )
|
205
|
+
#
|
206
|
+
# tvm.start
|
207
|
+
# # process a larger batch of 42 units
|
208
|
+
# duration2 = tvm.stop( 42 )
|
209
|
+
#
|
210
|
+
# At this point the rate of units per second is calculated as ( 12 + 42 ) / ( duration1 + duration2 )
|
211
|
+
#
|
212
|
+
# some_batch_rate = tvm.rate # returns ( 34 / ( duration1+duration2 ) )
|
213
|
+
#
|
214
|
+
def rate
|
215
|
+
@value_stats.sum / @timed_stats.sum
|
216
|
+
end
|
217
|
+
|
218
|
+
#
|
219
|
+
# :call-seq:
|
220
|
+
# metric.to_hash -> Hash
|
221
|
+
#
|
222
|
+
# Convert the metric to a hash
|
223
|
+
#
|
224
|
+
def to_hash
|
225
|
+
h = super
|
226
|
+
h['timed_stats'] = @timed_stats.to_hash
|
227
|
+
h['value_stats'] = @value_stats.to_hash( Stats::STATS - %w[ rate ] )
|
228
|
+
h['rate'] = self.rate
|
229
|
+
h['unit_count'] = self.unit_count
|
230
|
+
return h
|
231
|
+
end
|
232
|
+
|
233
|
+
|
234
|
+
end
|
235
|
+
end
|