hitimes 0.2.0

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.
@@ -0,0 +1,213 @@
1
+ #--
2
+ # Copyright (c) 2008 Jeremy Hinegardner
3
+ # All rights reserved. See LICENSE and/or COPYING for details.
4
+ #++
5
+
6
+ require 'hitimes'
7
+ require 'hitimes_ext'
8
+
9
+ module Hitimes
10
+ #
11
+ # A Timer combines together an Interval and a Stats object to provide
12
+ # aggregate information about timings.
13
+ #
14
+ # A Timer has many of the same methods as an Interval and would be used in
15
+ # preference to an Interval in those situations where you want to track
16
+ # statistics about the item you are monitoring.
17
+ #
18
+ class Timer
19
+
20
+ # holds all the statistics
21
+ attr_reader :stats
22
+
23
+ class << self
24
+
25
+ #
26
+ # :call-seq:
27
+ # Timer.now -> Timer
28
+ #
29
+ # Return a newly allocated Timer that has already been started
30
+ #
31
+ def now
32
+ t = Timer.new
33
+ t.start
34
+ return t
35
+ end
36
+
37
+ #
38
+ # :call-seq:
39
+ # Timer.measure { ... } -> Float
40
+ #
41
+ # Return the number of seconds that a block of code took to
42
+ # execute.
43
+ #
44
+ def measure( &block )
45
+ Interval.measure { yield }
46
+ end
47
+ end
48
+
49
+ #
50
+ # :call-seq:
51
+ # Timer.new -> Timer
52
+ #
53
+ def initialize
54
+ @stats = Stats.new
55
+ @current_interval = nil
56
+ end
57
+
58
+ #
59
+ # :call-seq:
60
+ # timer.current_interval -> Interval
61
+ #
62
+ # Return the current interval, if one doesn't exist create one.
63
+ #
64
+ def current_interval
65
+ @current_interval ||= Interval.new
66
+ end
67
+
68
+ #
69
+ # :call-seq:
70
+ # timer.running? -> true or false
71
+ #
72
+ # return whether or not the timer is currently running.
73
+ #
74
+ def running?
75
+ current_interval.running?
76
+ end
77
+
78
+ #
79
+ # :call-seq:
80
+ # timer.start -> nil
81
+ #
82
+ # Start the current timer, if the current timer is already started, then
83
+ # this is a noop.
84
+ #
85
+ def start
86
+ current_interval.start unless running?
87
+ nil
88
+ end
89
+
90
+ #
91
+ # :call-seq:
92
+ # timer.stop -> Float or nil
93
+ #
94
+ # Stop the current timer. This updates the stats and removes the current
95
+ # interval. If the timer is not running then this is a noop. If the
96
+ # timer was stopped then the duration of the last Interval is returned. If
97
+ # the timer was already stopped then false is returned.
98
+ #
99
+ def stop
100
+ if running? then
101
+ d = current_interval.stop
102
+ @current_interval = nil
103
+ stats.update( d )
104
+ return d
105
+ end
106
+ return false
107
+ end
108
+
109
+ #
110
+ # :call-seq:
111
+ # timer.measure { ... } -> Float
112
+ #
113
+ # Measure the execution of a block and add those stats to the running stats.
114
+ #
115
+ def measure( &block )
116
+ t = 0.0
117
+ begin
118
+ start
119
+ yield
120
+ ensure
121
+ t = stop
122
+ end
123
+ return t
124
+ end
125
+
126
+ #
127
+ # :call-seq:
128
+ # timer.split -> Flaot
129
+ #
130
+ # Split the current timer. Essentially, mark a split time. This means
131
+ # stop the current interval and create a new interval, but make sure
132
+ # that the new interval lines up exactly, timewise, behind the previous
133
+ # interval.
134
+ #
135
+ # If the timer is running, then split returns the duration of the previous
136
+ # interval, i.e. the split-time. If the timer is not running, nothing
137
+ # happens and false is returned.
138
+ #
139
+ def split
140
+ if running? then
141
+ next_interval = current_interval.split
142
+ d = current_interval.duration
143
+ stats.update( d )
144
+ @current_interval = next_interval
145
+ return d
146
+ end
147
+ return false
148
+ end
149
+
150
+ #
151
+ # :call-seq:
152
+ # timer.sum -> Float
153
+ # timer.duration -> Float
154
+ #
155
+ # The total time the timer has been measuring.
156
+ #
157
+ def sum
158
+ stats.sum
159
+ end
160
+ alias duration sum
161
+
162
+ #
163
+ # :call-seq:
164
+ # timer.mean -> Float
165
+ #
166
+ # The mean value of all the the stopped intervals. The current interval, if
167
+ # it is still running, is not included.
168
+ #
169
+ def mean
170
+ stats.mean
171
+ end
172
+
173
+ #
174
+ # :call-seq:
175
+ # timer.stddev -> Float
176
+ #
177
+ # The standard deviation of all the intervals
178
+ #
179
+ def stddev
180
+ stats.stddev
181
+ end
182
+
183
+ #
184
+ # :call-seq:
185
+ # timer.count -> Integer
186
+ #
187
+ # The count of intervals in this timer
188
+ #
189
+ def count
190
+ stats.count
191
+ end
192
+
193
+ #
194
+ # :call-seq:
195
+ # timer.max -> Float
196
+ #
197
+ # The maximum duration of all the intervals this Timer has seen
198
+ #
199
+ def max
200
+ stats.max
201
+ end
202
+
203
+ #
204
+ # :call-seq:
205
+ # timer.min -> Float
206
+ #
207
+ # The minimum duration of all the intervals this Timer has seen
208
+ #
209
+ def min
210
+ stats.min
211
+ end
212
+ end
213
+ end
@@ -0,0 +1,42 @@
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
+ # module containing all the version information about Hitimes
9
+ #
10
+ module Version
11
+
12
+ MAJOR = 0
13
+ MINOR = 2
14
+ BUILD = 0
15
+
16
+ #
17
+ # :call-seq:
18
+ # Version.to_a -> [ MAJOR, MINOR, BUILD ]
19
+ #
20
+ # Return the version as an array of Integers
21
+ #
22
+ def to_a
23
+ [MAJOR, MINOR, BUILD]
24
+ end
25
+
26
+ #
27
+ # :call-seq:
28
+ # Version.to_s -> MAJOR.MINOR.BUILD
29
+ #
30
+ # Return the version as a String with dotted notation
31
+ #
32
+ def to_s
33
+ to_a.join(".")
34
+ end
35
+
36
+ module_function :to_a
37
+ module_function :to_s
38
+
39
+ STRING = Version.to_s
40
+ end
41
+ VERSION = Version.to_s
42
+ end
@@ -0,0 +1,115 @@
1
+ require File.expand_path( File.join( File.dirname( __FILE__ ), "spec_helper.rb" ) )
2
+
3
+ require 'hitimes_ext'
4
+
5
+ describe Hitimes::Interval do
6
+ it "has a 0 duration when newly created" do
7
+ i = Hitimes::Interval.new
8
+ i.duration == 0.0
9
+ end
10
+
11
+ it "knows if it has been started" do
12
+ i = Hitimes::Interval.new
13
+ i.should_not be_started
14
+
15
+ i.start
16
+ i.should be_started
17
+ end
18
+
19
+ it "knows if it has been stopped" do
20
+ i = Hitimes::Interval.new
21
+ i.start
22
+ i.should_not be_stopped
23
+ i.stop
24
+ i.should be_stopped
25
+ end
26
+
27
+ it "knows if it is currently running" do
28
+ i = Hitimes::Interval.new
29
+ i.should_not be_running
30
+ i.start
31
+ i.should be_running
32
+ i.stop
33
+ i.should_not be_running
34
+ end
35
+
36
+ it "can time a block of code" do
37
+ d = Hitimes::Interval.measure do
38
+ sleep 0.2
39
+ end
40
+ d.should be_close(0.2, 0.01)
41
+ end
42
+
43
+ it "raises an error if measure is called with no block" do
44
+ lambda{ Hitimes::Interval.measure }.should raise_error( Hitimes::Error )
45
+ end
46
+
47
+ it "creates an interval via #now" do
48
+ i = Hitimes::Interval.now
49
+ i.should be_started
50
+ i.should_not be_stopped
51
+ end
52
+
53
+ it "calling duration multiple times returns successivly grater durations" do
54
+ i = Hitimes::Interval.new
55
+ i.start
56
+ y = i.duration
57
+ z = i.duration
58
+ z.should > y
59
+ end
60
+
61
+ it "calling start multiple times on has no effect after the first call" do
62
+ i = Hitimes::Interval.new
63
+ i.start.should == true
64
+ x = i.start_instant
65
+ i.start_instant.should > 0
66
+ i.start.should == false
67
+ x.should == i.start_instant
68
+ end
69
+
70
+ it "returns the duration on the first call to stop" do
71
+ i = Hitimes::Interval.now
72
+ d = i.stop
73
+ d.should be_instance_of( Float )
74
+ end
75
+
76
+ it "calling stop multiple times on has no effect after the first call" do
77
+ i = Hitimes::Interval.new
78
+ i.start.should == true
79
+ i.stop
80
+
81
+ x = i.stop_instant
82
+ i.stop_instant.should > 0
83
+ i.stop.should == false
84
+ x.should == i.stop_instant
85
+
86
+ end
87
+
88
+ it "only calculates duration once after stop is called" do
89
+ i = Hitimes::Interval.new
90
+ i.start
91
+ i.stop
92
+ x = i.duration
93
+ y = i.duration
94
+ x.object_id.should == y.object_id
95
+ end
96
+
97
+ describe "#split" do
98
+
99
+ it "creates a new Interval object" do
100
+ i = Hitimes::Interval.new
101
+ i.start
102
+ i2 = i.split
103
+ i.object_id.should_not == i2.object_id
104
+ end
105
+
106
+ it "with the stop instant equivialent to the previous Interval's start instant" do
107
+ i = Hitimes::Interval.new
108
+ i.start
109
+ i2 = i.split
110
+ i.stop_instant.should == i2.start_instant
111
+ end
112
+ end
113
+
114
+ end
115
+
@@ -0,0 +1,14 @@
1
+ require File.expand_path( File.join( File.dirname( __FILE__ ), "spec_helper.rb" ) )
2
+
3
+ require 'hitimes/paths'
4
+
5
+ describe Hitimes::Paths do
6
+ it "can access the root dir of the project" do
7
+ Hitimes::Paths.root_dir.should == File.expand_path( File.join( File.dirname( __FILE__ ), ".." ) ) + ::File::SEPARATOR
8
+ end
9
+
10
+ it "can access the lib path of the project" do
11
+ Hitimes::Paths.lib_path.should == File.expand_path( File.join( File.dirname( __FILE__ ), "..", "lib" ) ) + ::File::SEPARATOR
12
+ end
13
+
14
+ end
@@ -0,0 +1,6 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+
4
+ $: << File.expand_path(File.join(File.dirname(__FILE__),"..","ext"))
5
+ $: << File.expand_path(File.join(File.dirname(__FILE__),"..","lib"))
6
+
@@ -0,0 +1,44 @@
1
+ require File.expand_path( File.join( File.dirname( __FILE__ ), "spec_helper.rb" ) )
2
+
3
+ require 'hitimes_ext'
4
+
5
+ describe Hitimes::Stats do
6
+ before( :each ) do
7
+ @stats = Hitimes::Stats.new
8
+ @full_stats = Hitimes::Stats.new
9
+
10
+ [ 1, 2, 3].each { |i| @full_stats.update( i ) }
11
+ end
12
+
13
+ it "is initialized with 0 values" do
14
+ @stats.count.should == 0
15
+ @stats.min.should == 0.0
16
+ @stats.max.should == 0.0
17
+ @stats.sum.should == 0.0
18
+ end
19
+
20
+ it "calculates the mean correctly" do
21
+ @full_stats.mean.should == 2.0
22
+ end
23
+
24
+ it "tracks the maximum value" do
25
+ @full_stats.max.should == 3.0
26
+ end
27
+
28
+ it "tracks the minimum value" do
29
+ @full_stats.min.should == 1.0
30
+ end
31
+
32
+ it "tracks the count" do
33
+ @full_stats.count.should == 3
34
+ end
35
+
36
+ it "tracks the sum" do
37
+ @full_stats.sum.should == 6.0
38
+ end
39
+
40
+ it "calculates the standard deviation" do
41
+ @full_stats.stddev.should == 1.0
42
+ end
43
+
44
+ end
@@ -0,0 +1,98 @@
1
+ require File.expand_path( File.join( File.dirname( __FILE__ ), "spec_helper.rb" ) )
2
+
3
+ require 'hitimes/timer'
4
+
5
+ describe Hitimes::Timer do
6
+
7
+ it "knows if it is running or not" do
8
+ t = Hitimes::Timer.new
9
+ t.should_not be_running
10
+ t.start
11
+ t.should be_running
12
+ t.stop
13
+ t.should_not be_running
14
+ end
15
+
16
+ it "#split returns the last duration and the timer is still running" do
17
+ t = Hitimes::Timer.now
18
+ d = t.split
19
+ t.should be_running
20
+ d.should > 0
21
+ t.count.should == 1
22
+ t.duration.should == d
23
+ end
24
+
25
+ it "#stop returns false if called more than once in a row" do
26
+ t = Hitimes::Timer.new
27
+ t.start
28
+ t.stop.should > 0
29
+ t.stop.should == false
30
+ end
31
+
32
+ it "does not count a currently running interval as an interval in calculations" do
33
+ t = Hitimes::Timer.new
34
+ t.start
35
+ t.count.should == 0
36
+ t.split
37
+ t.count.should == 1
38
+ end
39
+
40
+ it "#split called on a stopped timer does nothing" do
41
+ t = Hitimes::Timer.new
42
+ t.start
43
+ t.stop
44
+ t.split.should == false
45
+ end
46
+
47
+ it "calculates the mean of the durations" do
48
+ t = Hitimes::Timer.new
49
+ 2.times { t.start ; sleep 0.05 ; t.stop }
50
+ t.mean.should > 0.04
51
+ end
52
+
53
+ it "calculates the stddev of the durations" do
54
+ t = Hitimes::Timer.new
55
+ 2.times { t.start ; sleep 0.05 ; t.stop }
56
+ t.stddev.should > 0.0
57
+ end
58
+
59
+ it "returns 0.0 for stddev if there is no data" do
60
+ t = Hitimes::Timer.new
61
+ t.stddev.should == 0.0
62
+ end
63
+
64
+ it "retuns 0.0 for mean if there is no data" do
65
+ Hitimes::Timer.new.mean.should == 0.0
66
+ end
67
+
68
+ it "keeps track of the min value" do
69
+ t = Hitimes::Timer.new
70
+ 2.times { t.start ; sleep 0.05 ; t.stop }
71
+ t.min.should > 0
72
+ end
73
+
74
+ it "keeps track of the max value" do
75
+ t = Hitimes::Timer.new
76
+ 2.times { t.start ; sleep 0.05 ; t.stop }
77
+ t.max.should > 0
78
+ end
79
+
80
+ it "can create an already running timer" do
81
+ t = Hitimes::Timer.now
82
+ t.should be_running
83
+ end
84
+
85
+ it "can measure a block of code's execution time" do
86
+ dur = Hitimes::Timer.measure { sleep 0.05 }
87
+ dur.should > 0.025
88
+ end
89
+
90
+ it "can measuer a block of code from an instance" do
91
+ t = Hitimes::Timer.new
92
+ 3.times { t.measure { sleep 0.05 } }
93
+ t.duration.should > 0.14
94
+ t.count.should == 3
95
+ end
96
+
97
+ end
98
+