hitimes 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+