hitimes 1.3.0-x64-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTING.md +57 -0
  3. data/HISTORY.md +124 -0
  4. data/LICENSE +16 -0
  5. data/Manifest.txt +44 -0
  6. data/README.md +200 -0
  7. data/Rakefile +28 -0
  8. data/examples/benchmarks.rb +113 -0
  9. data/examples/stats.rb +31 -0
  10. data/ext/hitimes/c/extconf.rb +24 -0
  11. data/ext/hitimes/c/hitimes.c +37 -0
  12. data/ext/hitimes/c/hitimes_instant_clock_gettime.c +28 -0
  13. data/ext/hitimes/c/hitimes_instant_osx.c +45 -0
  14. data/ext/hitimes/c/hitimes_instant_windows.c +27 -0
  15. data/ext/hitimes/c/hitimes_interval.c +370 -0
  16. data/ext/hitimes/c/hitimes_interval.h +73 -0
  17. data/ext/hitimes/c/hitimes_stats.c +269 -0
  18. data/ext/hitimes/c/hitimes_stats.h +30 -0
  19. data/ext/hitimes/java/src/hitimes/Hitimes.java +66 -0
  20. data/ext/hitimes/java/src/hitimes/HitimesInterval.java +176 -0
  21. data/ext/hitimes/java/src/hitimes/HitimesService.java +16 -0
  22. data/ext/hitimes/java/src/hitimes/HitimesStats.java +112 -0
  23. data/lib/hitimes.rb +66 -0
  24. data/lib/hitimes/2.0/hitimes.so +0 -0
  25. data/lib/hitimes/2.1/hitimes.so +0 -0
  26. data/lib/hitimes/2.2/hitimes.so +0 -0
  27. data/lib/hitimes/2.3/hitimes.so +0 -0
  28. data/lib/hitimes/2.4/hitimes.so +0 -0
  29. data/lib/hitimes/2.5/hitimes.so +0 -0
  30. data/lib/hitimes/metric.rb +118 -0
  31. data/lib/hitimes/mutexed_stats.rb +32 -0
  32. data/lib/hitimes/paths.rb +53 -0
  33. data/lib/hitimes/stats.rb +58 -0
  34. data/lib/hitimes/timed_metric.rb +176 -0
  35. data/lib/hitimes/timed_value_metric.rb +233 -0
  36. data/lib/hitimes/value_metric.rb +71 -0
  37. data/lib/hitimes/version.rb +8 -0
  38. data/spec/hitimes_spec.rb +24 -0
  39. data/spec/interval_spec.rb +136 -0
  40. data/spec/metric_spec.rb +28 -0
  41. data/spec/mutex_stats_spec.rb +36 -0
  42. data/spec/paths_spec.rb +11 -0
  43. data/spec/spec_helper.rb +11 -0
  44. data/spec/stats_spec.rb +98 -0
  45. data/spec/timed_metric_spec.rb +155 -0
  46. data/spec/timed_value_metric_spec.rb +171 -0
  47. data/spec/value_metric_spec.rb +108 -0
  48. data/spec/version_spec.rb +7 -0
  49. data/tasks/default.rake +242 -0
  50. data/tasks/extension.rake +38 -0
  51. data/tasks/this.rb +208 -0
  52. metadata +216 -0
@@ -0,0 +1,176 @@
1
+ #--
2
+ # Copyright (c) 2008, 2009 Jeremy Hinegardner
3
+ # All rights reserved. See LICENSE and/or COPYING for details.
4
+ #++
5
+
6
+ require 'forwardable'
7
+ module Hitimes
8
+ #
9
+ # A TimedMetric holds the metrics on how long it takes to do something. For
10
+ # example, measuring how long a method takes to operate.
11
+ #
12
+ # tm = TimedMetric.new( 'my-method' )
13
+ #
14
+ # 200.times do
15
+ # my_method_result = tm.measure do
16
+ # my_method( ... )
17
+ # end
18
+ # end
19
+ #
20
+ # puts "#{ tm.name } operated at a rate of #{ tm.rate } calls per second"
21
+ #
22
+ # Since TimedMetric is a child class of Metric make sure to look at the
23
+ # Metric API also.
24
+ #
25
+ # A TimedMetric measures the execution time of an option with the Interval
26
+ # class.
27
+ #
28
+ # A TimedMetric contains a Stats object, therefore TimedMetric has +count+, +max+,
29
+ # +mean+, +min+, +rate+, +stddev+, +sum+, +sumsq+ methods that delegate to that Stats
30
+ # object for convenience.
31
+ #
32
+ #
33
+ class TimedMetric < Metric
34
+ # holds all the statistics
35
+ attr_reader :stats
36
+
37
+ class << TimedMetric
38
+ #
39
+ # :call-seq:
40
+ # TimedMetric.now -> TimedMetric
41
+ #
42
+ # Return a TimedMetric that has been started
43
+ #
44
+ def now( name, additional_data = {} )
45
+ t = TimedMetric.new( name, additional_data )
46
+ t.start
47
+ return t
48
+ end
49
+ end
50
+
51
+ #
52
+ # :call-seq:
53
+ # TimedMetric.new( 'name') -> TimedMetric
54
+ # TimedMetric.new( 'name', 'other' => 'data') -> TimedMetric
55
+ #
56
+ # Create a new TimedMetric giving it a name and additional data.
57
+ # +additional_data+ may be anything that follows the +to_hash+ protocol
58
+ #
59
+ def initialize( name, additional_data = {} )
60
+ super( name, additional_data )
61
+ @stats = Stats.new
62
+ @current_interval = Interval.new
63
+ end
64
+
65
+ #
66
+ # :call-seq:
67
+ # timed_metric.running? -> true or false
68
+ #
69
+ # return whether or not the timer is currently running.
70
+ #
71
+ def running?
72
+ @current_interval.running?
73
+ end
74
+
75
+ #
76
+ # :call-seq:
77
+ # timed_metric.start -> nil
78
+ #
79
+ # Start the current metric, if the current metric is already started, then
80
+ # this is a noop.
81
+ #
82
+ def start
83
+ if not @current_interval.running? then
84
+ @current_interval.start
85
+ @sampling_start_time ||= self.utc_microseconds()
86
+ @sampling_start_interval ||= Interval.now
87
+ end
88
+ nil
89
+ end
90
+
91
+ #
92
+ # :call-seq:
93
+ # timed_metric.stop -> Float or nil
94
+ #
95
+ # Stop the current metric. This updates the stats and removes the current
96
+ # interval. If the timer was stopped then the duration of the last Interval
97
+ # is returned. If the timer was already stopped then false is returned and
98
+ # no stats are updated.
99
+ #
100
+ def stop
101
+ if @current_interval.running? then
102
+ d = @current_interval.stop
103
+ @stats.update( d )
104
+ @current_interval = Interval.new
105
+
106
+ # update the length of time we have been sampling
107
+ @sampling_delta = @sampling_start_interval.duration_so_far
108
+
109
+ return d
110
+ end
111
+ return false
112
+ end
113
+
114
+ #
115
+ # :call-seq:
116
+ # timed_metric.measure { ... } -> Object
117
+ #
118
+ # Measure the execution of a block and add those stats to the running stats.
119
+ # The return value is the return value of the block
120
+ #
121
+ def measure( &block )
122
+ return_value = nil
123
+ begin
124
+ start
125
+ return_value = yield
126
+ ensure
127
+ stop
128
+ end
129
+ return return_value
130
+ end
131
+
132
+ #
133
+ # :call-seq:
134
+ # timed_metric.split -> Float
135
+ #
136
+ # Split the current TimedMetric. Essentially, mark a split time. This means
137
+ # stop the current interval and create a new interval, but make sure
138
+ # that the new interval lines up exactly, timewise, behind the previous
139
+ # interval.
140
+ #
141
+ # If the timer is running, then split returns the duration of the previous
142
+ # interval, i.e. the split-time. If the timer is not running, nothing
143
+ # happens and false is returned.
144
+ #
145
+ def split
146
+ if @current_interval.running? then
147
+ next_interval = @current_interval.split
148
+ d = @current_interval.duration
149
+ @stats.update( d )
150
+ @current_interval = next_interval
151
+ return d
152
+ end
153
+ return false
154
+ end
155
+
156
+ #
157
+ # :call-seq:
158
+ # metric.to_hash -> Hash
159
+ #
160
+ # Convert the metric to a hash
161
+ #
162
+ def to_hash
163
+ h = super
164
+ Stats::STATS.each do |s|
165
+ h[s] = self.send( s )
166
+ end
167
+ return h
168
+ end
169
+
170
+
171
+ # forward appropriate calls directly to the stats object
172
+ extend Forwardable
173
+ def_delegators :@stats, :count, :max, :mean, :min, :rate, :stddev, :sum, :sumsq
174
+ alias :duration :sum
175
+ end
176
+ end
@@ -0,0 +1,233 @@
1
+ #--
2
+ # Copyright (c) 2008, 2009 Jeremy Hinegardner
3
+ # All rights reserved. See LICENSE and/or COPYING for details.
4
+ #++
5
+
6
+ module Hitimes
7
+ #
8
+ # A TimedValueMetric holds the metrics on how long it takes to do a batch of something.
9
+ # something. For measuring how long a method takes to operate on N items.
10
+ #
11
+ # tm = TimedValueMetric.new( 'my-batch-method' )
12
+ #
13
+ # 42.times do
14
+ # tm.start
15
+ # number_of_items_processed = do_something
16
+ # tm.stop( number_of_items_processed )
17
+ # end
18
+ #
19
+ # puts "#{ tm.name } operated at a rate of #{ tm.rate } calls per second"
20
+ #
21
+ # TimedValueMetric combines the usefulness of a ValueMetric and a TimedMetric.
22
+ # The stats are available for both the time it took to do the operation and
23
+ # the sizes of the batches that were run.
24
+ #
25
+ # A TimedValueMetric keeps track of both the time it took to do an operation
26
+ # and the size of the batch that was operated on. These metrics are kept
27
+ # separately as +timed_stats+ and +value_stats+ accessors.
28
+ #
29
+ class TimedValueMetric < Metric
30
+ # holds all the Timed statistics
31
+ attr_reader :timed_stats
32
+
33
+ # holds all the Value statistics
34
+ attr_reader :value_stats
35
+
36
+ class << TimedValueMetric
37
+ #
38
+ # :call-seq:
39
+ # TimedValueMetric.now( 'name' ) -> TimedValueMetric
40
+ #
41
+ # Return a TimedValueMetric that has been started
42
+ #
43
+ def now( name, additional_data = {} )
44
+ t = TimedValueMetric.new( name, additional_data )
45
+ t.start
46
+ return t
47
+ end
48
+ end
49
+
50
+ #
51
+ # :call-seq:
52
+ # TimedValueMetric.new( 'name') -> TimedValueMetric
53
+ # TimedValueMetric.new( 'name', 'other' => 'data') -> TimedValueMetric
54
+ #
55
+ # Create a new TimedValueMetric giving it a name and additional data.
56
+ # +additional_data+ may be anything that follows the +to_hash+ protocol
57
+ #
58
+ def initialize( name, additional_data = {} )
59
+ super( name, additional_data )
60
+ @timed_stats = Stats.new
61
+ @value_stats = Stats.new
62
+ @current_interval = Interval.new
63
+ end
64
+
65
+ #
66
+ # :call-seq:
67
+ # timed_value_metric.running? -> true or false
68
+ #
69
+ # return whether or not the metric is currently timing something.
70
+ #
71
+ def running?
72
+ @current_interval.running?
73
+ end
74
+
75
+ #
76
+ # :call-seq:
77
+ # timed_value_metric.start -> nil
78
+ #
79
+ # Start the current timer, if the current timer is already started, then
80
+ # this is a noop.
81
+ #
82
+ def start
83
+ if not @current_interval.running? then
84
+ @current_interval.start
85
+ @sampling_start_time ||= self.utc_microseconds()
86
+ @sampling_start_interval ||= Interval.now
87
+ end
88
+ nil
89
+ end
90
+
91
+ #
92
+ # :call-seq:
93
+ # timed_value_metric.stop( count ) -> Float or nil
94
+ #
95
+ # Stop the current metric. The +count+ parameter must be a
96
+ # value to update to the _value_ portion of the TimedValueMetric. Generally
97
+ # this is probably the number of things that were operated upon since
98
+ # +start+ was invoked.
99
+ #
100
+ # This updates both the +value_stats+ and +timed_stats+ stats and removes
101
+ # the current interval. If the metric is stopped then the duration of the
102
+ # last Interval is returned. If the metric was already stopped before this
103
+ # call, then false is returned and no stats are updated.
104
+ #
105
+ #
106
+ def stop( value )
107
+ if @current_interval.running? then
108
+ d = @current_interval.stop
109
+ @timed_stats.update( d )
110
+ @current_interval = Interval.new
111
+ @value_stats.update( value )
112
+
113
+ # update the lenght of time we have been sampling
114
+ @sampling_delta = @sampling_start_interval.duration_so_far
115
+
116
+ return d
117
+ end
118
+ return false
119
+ end
120
+
121
+ #
122
+ # :call-seq:
123
+ # timed_value_metric.measure( value ) { ... } -> Object
124
+ #
125
+ # Measure the execution of a block and add those stats to the running stats.
126
+ # The return value is the return value of the block. A value must be passed
127
+ # into +measure+ to update the +value_stats+ portion of the TimedValueMetric.
128
+ #
129
+ def measure( value, &block )
130
+ return_value = nil
131
+ begin
132
+ start
133
+ return_value = yield
134
+ ensure
135
+ stop( value )
136
+ end
137
+ return return_value
138
+ end
139
+
140
+ #
141
+ # :call-seq:
142
+ # timed_value_metric.split( value ) -> Float
143
+ #
144
+ # Split the current metric. Essentially, mark a split time. This means
145
+ # stop the current interval, with the givein +value+ and create a new
146
+ # interval, but make sure that the new interval lines up exactly, timewise,
147
+ # behind the previous interval.
148
+ #
149
+ # If the metric is running, then split returns the duration of the previous
150
+ # interval, i.e. the split-time. If the metric is not running, nothing
151
+ # happens, no stats are updated, and false is returned.
152
+ #
153
+ #
154
+ def split( value )
155
+ if @current_interval.running? then
156
+ next_interval = @current_interval.split
157
+ d = @current_interval.duration
158
+ @timed_stats.update( d )
159
+ @value_stats.update( value )
160
+ @current_interval = next_interval
161
+ return d
162
+ end
163
+ return false
164
+ end
165
+
166
+ #
167
+ # :call-seq:
168
+ # timed_value_metric.duration -> Float
169
+ #
170
+ # The duration of measured time from the metric.
171
+ #
172
+ def duration
173
+ @timed_stats.sum
174
+ end
175
+
176
+ #
177
+ # :call-seq:
178
+ # timed_value_metric.unit_count -> Float
179
+ #
180
+ # The sum of all values passed to +stop+ or +skip+ or +measure+
181
+ #
182
+ def unit_count
183
+ @value_stats.sum
184
+ end
185
+
186
+ #
187
+ # :call-seq:
188
+ # timed_value_metric.rate -> Float
189
+ #
190
+ # Rate in the context of the TimedValueMetric is different than the
191
+ # TimedMetric. In the TimedValueMetric, each measurement of time is
192
+ # associated with a quantity of things done during that unit of time. So
193
+ # the +rate+ for a TimedValueMetric is the (sum of all quantities sampled) /
194
+ # ( sum of all durations measured )
195
+ #
196
+ # For example, say you were measuring, using a TimedValueMetric batch jobs
197
+ # that had individual units of work.
198
+ #
199
+ # tvm = TimedValueMetric.new( 'some-batch' )
200
+ # tvm.start
201
+ # # process a batch of 12 units
202
+ # duration1 = tvm.stop( 12 )
203
+ #
204
+ # tvm.start
205
+ # # process a larger batch of 42 units
206
+ # duration2 = tvm.stop( 42 )
207
+ #
208
+ # At this point the rate of units per second is calculated as ( 12 + 42 ) / ( duration1 + duration2 )
209
+ #
210
+ # some_batch_rate = tvm.rate # returns ( 34 / ( duration1+duration2 ) )
211
+ #
212
+ def rate
213
+ @value_stats.sum / @timed_stats.sum
214
+ end
215
+
216
+ #
217
+ # :call-seq:
218
+ # metric.to_hash -> Hash
219
+ #
220
+ # Convert the metric to a hash
221
+ #
222
+ def to_hash
223
+ h = super
224
+ h['timed_stats'] = @timed_stats.to_hash
225
+ h['value_stats'] = @value_stats.to_hash( Stats::STATS - %w[ rate ] )
226
+ h['rate'] = self.rate
227
+ h['unit_count'] = self.unit_count
228
+ return h
229
+ end
230
+
231
+
232
+ end
233
+ end
@@ -0,0 +1,71 @@
1
+ #--
2
+ # Copyright (c) 2008, 2009 Jeremy Hinegardner
3
+ # All rights reserved. See LICENSE and/or COPYING for details.
4
+ #++
5
+
6
+ require 'forwardable'
7
+ module Hitimes
8
+ #
9
+ # A ValueMetric holds the data from measuring a single value over a period of
10
+ # time. In most cases this may be a single measurement at a single point in
11
+ # time.
12
+ #
13
+ # A good example of a ValueMetric is measuring the number of items in a queue.
14
+ #
15
+ # A ValueMetric contains a Stats object, therefore ValueMetric has +count+, +max+,
16
+ # +mean+, +min+, +stddev+, +sum+, +sumsq+ methods that delegate to that Stats
17
+ # object for convenience.
18
+ #
19
+ class ValueMetric < Metric
20
+
21
+ # holds all the statistics
22
+ attr_reader :stats
23
+
24
+ #
25
+ # :call-seq:
26
+ # ValueMetric.new( 'my_metric' ) -> ValueMetric
27
+ # ValueMetric.new( 'my_metric', 'foo' => 'bar', 'this' => 42 ) -> ValueMetric
28
+ #
29
+ # Create a new ValueMetric giving it a name and additional data.
30
+ # +additional_data+ may be anything that follows the +to_hash+ protocol.
31
+ #
32
+ def initialize( name, additional_data = {} )
33
+ super( name, additional_data )
34
+ @stats = Stats.new
35
+ end
36
+
37
+ #
38
+ # :call-seq:
39
+ # metric.measure( value ) -> Float
40
+ #
41
+ # Give the +value+ as the measurement to the metric. The value is returned
42
+ #
43
+ def measure( value )
44
+ @sampling_start_time ||= self.utc_microseconds()
45
+ @sampling_start_interval ||= Interval.now
46
+
47
+ @stats.update( value )
48
+
49
+ # update the length of time we have been sampling
50
+ @sampling_delta = @sampling_start_interval.duration_so_far
51
+ end
52
+
53
+ #
54
+ # :call-seq:
55
+ # metric.to_hash -> Hash
56
+ #
57
+ # Convert the metric to a hash
58
+ #
59
+ def to_hash
60
+ h = super
61
+ (Stats::STATS - %w[ rate ]).each do |s|
62
+ h[s] = self.send( s )
63
+ end
64
+ return h
65
+ end
66
+
67
+ # forward appropriate calls directly to the stats object
68
+ extend Forwardable
69
+ def_delegators :@stats, :count, :max, :mean, :min, :stddev, :sum, :sumsq
70
+ end
71
+ end