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,8 @@
1
+ #--
2
+ # Copyright (c) 2008 Jeremy Hinegardner
3
+ # All rights reserved. See LICENSE and/or COPYING for details
4
+ #++
5
+
6
+ module Hitimes
7
+ VERSION = "1.3.0"
8
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hitimes do
4
+ it "can time a block of code" do
5
+ d = Hitimes.measure do
6
+ sleep 0.2
7
+ end
8
+ d.must_be_close_to(0.2, 0.002)
9
+ end
10
+
11
+ it "raises an error if measure is called with no block" do
12
+ lambda{ Hitimes.measure }.must_raise( Hitimes::Error )
13
+ end
14
+
15
+ it "has the raw instant value" do
16
+ v = Hitimes.raw_instant
17
+ v.must_be :>, 0
18
+ end
19
+
20
+ it "has access to the instant conversion factor" do
21
+ f = Hitimes::INSTANT_CONVERSION_FACTOR
22
+ f.must_be :>, 0
23
+ end
24
+ end
@@ -0,0 +1,136 @@
1
+ require "spec_helper"
2
+
3
+ describe Hitimes::Interval do
4
+ it "raises an error if duration is called on a non-started interval" do
5
+ i = Hitimes::Interval.new
6
+ lambda{ i.duration }.must_raise( Hitimes::Error, /\AAttempt to report a duration on an interval that has not started\Z/ )
7
+ end
8
+
9
+ it "raises an error if stop is called on a non-started interval" do
10
+ i = Hitimes::Interval.new
11
+ lambda { i.stop }.must_raise( Hitimes::Error, /\AAttempt to stop an interval that has not started\Z/ )
12
+ end
13
+
14
+ it "knows if it has been started" do
15
+ i = Hitimes::Interval.new
16
+ i.started?.must_equal false
17
+
18
+ i.start
19
+ i.started?.must_equal true
20
+ end
21
+
22
+ it "knows if it has been stopped" do
23
+ i = Hitimes::Interval.new
24
+ i.start
25
+ i.stopped?.must_equal false
26
+ i.stop
27
+ i.stopped?.must_equal true
28
+ end
29
+
30
+ it "knows if it is currently running" do
31
+ i = Hitimes::Interval.new
32
+ i.running?.must_equal false
33
+ i.start
34
+ i.running?.must_equal true
35
+ i.stop
36
+ i.running?.must_equal false
37
+ end
38
+
39
+ it "can time a block of code" do
40
+ d = Hitimes::Interval.measure do
41
+ sleep 0.2
42
+ end
43
+ d.must_be_close_to(0.2, 0.002)
44
+ end
45
+
46
+ it "raises an error if measure is called with no block" do
47
+ lambda{ Hitimes::Interval.measure }.must_raise( Hitimes::Error, /\ANo block given to Interval.measure\Z/ )
48
+ end
49
+
50
+ it "creates an interval via #now" do
51
+ i = Hitimes::Interval.now
52
+ i.started?.must_equal true
53
+ i.stopped?.must_equal false
54
+ end
55
+
56
+ it "calling duration multiple times returns successivly grater durations" do
57
+ i = Hitimes::Interval.new
58
+ i.start
59
+ y = i.duration
60
+ z = i.duration
61
+ z.must_be :>, y
62
+ end
63
+
64
+ it "calling start multiple times on has no effect after the first call" do
65
+ i = Hitimes::Interval.new
66
+ i.start.must_equal true
67
+ x = i.start_instant
68
+ i.start_instant.must_be :>, 0
69
+ i.start.must_equal false
70
+ x.must_equal i.start_instant
71
+ end
72
+
73
+ it "returns the duration on the first call to stop" do
74
+ i = Hitimes::Interval.now
75
+ d = i.stop
76
+ d.must_be_instance_of( Float )
77
+ end
78
+
79
+ it "calling stop multiple times on has no effect after the first call" do
80
+ i = Hitimes::Interval.new
81
+ i.start.must_equal true
82
+ i.stop
83
+
84
+ x = i.stop_instant
85
+ i.stop_instant.must_be :>, 0
86
+ i.stop.must_equal false
87
+ x.must_equal i.stop_instant
88
+
89
+ end
90
+
91
+ it "duration does not change after stop is calledd" do
92
+ i = Hitimes::Interval.new
93
+ i.start
94
+ x = i.stop
95
+ y = i.duration
96
+ i.stop.must_equal false
97
+
98
+ z = i.duration
99
+
100
+ x.must_equal y
101
+ x.must_equal z
102
+
103
+ y.must_equal z
104
+ end
105
+
106
+ it "can return how much time has elapsed from the start without stopping the interval" do
107
+ i = Hitimes::Interval.new
108
+ i.start
109
+ x = i.duration_so_far
110
+ i.running?.must_equal true
111
+ y = i.duration_so_far
112
+ i.stop
113
+ x.must_be :<, y
114
+ x.must_be :<, i.duration
115
+ y.must_be :<, i.duration
116
+ end
117
+
118
+ describe "#split" do
119
+
120
+ it "creates a new Interval object" do
121
+ i = Hitimes::Interval.new
122
+ i.start
123
+ i2 = i.split
124
+ i.object_id.wont_equal i2.object_id
125
+ end
126
+
127
+ it "with the stop instant equivialent to the previous Interval's start instant" do
128
+ i = Hitimes::Interval.new
129
+ i.start
130
+ i2 = i.split
131
+ i.stop_instant.must_equal i2.start_instant
132
+ end
133
+ end
134
+
135
+ end
136
+
@@ -0,0 +1,28 @@
1
+ require "spec_helper"
2
+
3
+ describe Hitimes::Metric do
4
+ before( :each ) do
5
+ @metric = Hitimes::Metric.new( "testing" )
6
+ end
7
+
8
+ it 'has a name' do
9
+ @metric.name.must_equal "testing"
10
+ end
11
+
12
+ it "has associated data from initialization" do
13
+ m = Hitimes::Metric.new( "more-data", 'foo' => 'bar', 'this' => 'that' )
14
+ m.additional_data['foo'].must_equal 'bar'
15
+ m.additional_data['this'].must_equal 'that'
16
+
17
+ m = Hitimes::Metric.new( "more-data", { 'foo' => 'bar', 'this' => 'that' } )
18
+ m.additional_data['foo'].must_equal 'bar'
19
+ m.additional_data['this'].must_equal 'that'
20
+ end
21
+
22
+ it "initially has no sampling times" do
23
+ @metric.sampling_start_time.must_be_nil
24
+ @metric.sampling_stop_time.must_be_nil
25
+ end
26
+ end
27
+
28
+
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hitimes::MutexedStats do
4
+ before( :each ) do
5
+ @threads = 5
6
+ @iters = 10_000
7
+ @final_value = @threads * @iters
8
+ end
9
+
10
+ def run_with_scissors( stats, threads, iters )
11
+ spool = []
12
+ threads.times do |t|
13
+ spool << Thread.new { iters.times{ stats.update( 1 ) } }
14
+ end
15
+ spool.each { |t| t.join }
16
+ return stats
17
+ end
18
+
19
+ if (not defined? RUBY_ENGINE) or (RUBY_ENGINE == "ruby") then
20
+ it "Hitimes::Stats is threadsafe" do
21
+ stats = run_with_scissors( ::Hitimes::Stats.new, @threads, @iters )
22
+ stats.count.must_equal @final_value
23
+ end
24
+ else
25
+ it "Hitimes::Stats is not threadsafe" do
26
+ stats = run_with_scissors( ::Hitimes::Stats.new, @threads, @iters )
27
+ stats.count.wont_equal @final_value
28
+ end
29
+ end
30
+
31
+ it "has a threadsafe update" do
32
+ stats = run_with_scissors( ::Hitimes::MutexedStats.new, @threads, @iters )
33
+ stats.count.must_equal @final_value
34
+ end
35
+
36
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hitimes::Paths do
4
+ it "can access the root dir of the project" do
5
+ Hitimes::Paths.root_dir.must_equal File.expand_path( File.join( File.dirname( __FILE__ ), ".." ) ) + ::File::SEPARATOR
6
+ end
7
+
8
+ it "can access the lib path of the project" do
9
+ Hitimes::Paths.lib_path.must_equal File.expand_path( File.join( File.dirname( __FILE__ ), "..", "lib" ) ) + ::File::SEPARATOR
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ if RUBY_VERSION >= '1.9.2' then
2
+ require 'simplecov'
3
+ puts "Using coverage!"
4
+ SimpleCov.start if ENV['COVERAGE']
5
+ end
6
+
7
+ gem 'minitest'
8
+ require 'hitimes'
9
+ require 'minitest/autorun'
10
+ require 'minitest/pride'
11
+
@@ -0,0 +1,98 @@
1
+ require 'spec_helper'
2
+ require 'json'
3
+
4
+ describe Hitimes::Stats do
5
+ before( :each ) do
6
+ @stats = Hitimes::Stats.new
7
+ @full_stats = Hitimes::Stats.new
8
+
9
+ [ 1, 2, 3].each { |i| @full_stats.update( i ) }
10
+ end
11
+
12
+ it "is initialized with 0 values" do
13
+ @stats.count.must_equal 0
14
+ @stats.min.must_equal 0.0
15
+ @stats.max.must_equal 0.0
16
+ @stats.sum.must_equal 0.0
17
+ @stats.rate.must_equal 0.0
18
+ end
19
+
20
+ it "calculates the mean correctly" do
21
+ @full_stats.mean.must_equal 2.0
22
+ end
23
+
24
+ it "calculates the rate correctly" do
25
+ @full_stats.rate.must_equal 0.5
26
+ end
27
+
28
+ it "tracks the maximum value" do
29
+ @full_stats.max.must_equal 3.0
30
+ end
31
+
32
+ it "tracks the minimum value" do
33
+ @full_stats.min.must_equal 1.0
34
+ end
35
+
36
+ it "tracks the count" do
37
+ @full_stats.count.must_equal 3
38
+ end
39
+
40
+ it "tracks the sum" do
41
+ @full_stats.sum.must_equal 6.0
42
+ end
43
+
44
+ it "calculates the standard deviation" do
45
+ @full_stats.stddev.must_equal 1.0
46
+ end
47
+
48
+ it "calculates the sum of squares " do
49
+ @full_stats.sumsq.must_equal 14.0
50
+ end
51
+
52
+ describe "#to_hash " do
53
+ it "converts to a Hash" do
54
+ h = @full_stats.to_hash
55
+ h.size.must_equal ::Hitimes::Stats::STATS.size
56
+ h.keys.sort.must_equal ::Hitimes::Stats::STATS
57
+ end
58
+
59
+ it "converts to a limited Hash if given arguments" do
60
+ h = @full_stats.to_hash( "min", "max", "mean" )
61
+ h.size.must_equal 3
62
+ h.keys.sort.must_equal %w[ max mean min ]
63
+
64
+ h = @full_stats.to_hash( %w[ count rate ] )
65
+ h.size.must_equal 2
66
+ h.keys.sort.must_equal %w[ count rate ]
67
+ end
68
+
69
+ it "raises NoMethodError if an invalid stat is used" do
70
+ lambda { @full_stats.to_hash( "wibble" ) }.must_raise( NoMethodError )
71
+ end
72
+ end
73
+
74
+ describe "#to_json" do
75
+ it "converts to a json string" do
76
+ j = @full_stats.to_json
77
+ h = JSON.parse( j )
78
+ h.size.must_equal ::Hitimes::Stats::STATS.size
79
+ h.keys.sort.must_equal ::Hitimes::Stats::STATS
80
+ end
81
+
82
+ it "converts to a limited Hash if given arguments" do
83
+ j = @full_stats.to_json( "min", "max", "mean" )
84
+ h = JSON.parse( j )
85
+ h.size.must_equal 3
86
+ h.keys.sort.must_equal %w[ max mean min ]
87
+
88
+ j = @full_stats.to_json( %w[ count rate ] )
89
+ h = JSON.parse( j )
90
+ h.size.must_equal 2
91
+ h.keys.sort.must_equal %w[ count rate ]
92
+ end
93
+
94
+ it "raises NoMethodError if an invalid stat is used" do
95
+ lambda { @full_stats.to_json( "wibble" ) }.must_raise( NoMethodError )
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,155 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hitimes::TimedMetric do
4
+ before( :each ) do
5
+ @tm = Hitimes::TimedMetric.new( 'test-timed-metric' )
6
+ end
7
+
8
+ it "knows if it is running or not" do
9
+ @tm.running?.must_equal false
10
+ @tm.start
11
+ @tm.running?.must_equal true
12
+ @tm.stop
13
+ @tm.running?.must_equal false
14
+ end
15
+
16
+ it "#split returns the last duration and the timer is still running" do
17
+ @tm.start
18
+ d = @tm.split
19
+ @tm.running?.must_equal true
20
+ d.must_be :>, 0
21
+ @tm.count.must_equal 1
22
+ @tm.duration.must_equal d
23
+ end
24
+
25
+ it "#stop returns false if called more than once in a row" do
26
+ @tm.start
27
+ @tm.stop.must_be :>, 0
28
+ @tm.stop.must_equal false
29
+ end
30
+
31
+ it "does not count a currently running interval as an interval in calculations" do
32
+ @tm.start
33
+ @tm.count.must_equal 0
34
+ @tm.split
35
+ @tm.count.must_equal 1
36
+ end
37
+
38
+ it "#split called on a stopped timer does nothing" do
39
+ @tm.start
40
+ @tm.stop
41
+ @tm.split.must_equal false
42
+ end
43
+
44
+ it "calculates the mean of the durations" do
45
+ 2.times { @tm.start ; sleep 0.05 ; @tm.stop }
46
+ @tm.mean.must_be_close_to(0.05, 0.002)
47
+ end
48
+
49
+ it "calculates the rate of the counts " do
50
+ 5.times { @tm.start ; sleep 0.05 ; @tm.stop }
51
+ @tm.rate.must_be_close_to(20.00, 0.5)
52
+ end
53
+
54
+
55
+ it "calculates the stddev of the durations" do
56
+ 3.times { |x| @tm.start ; sleep(0.05 * x) ; @tm.stop }
57
+ @tm.stddev.must_be_close_to(0.05)
58
+ end
59
+
60
+ it "returns 0.0 for stddev if there is no data" do
61
+ @tm.stddev.must_equal 0.0
62
+ end
63
+
64
+ it "keeps track of the min value" do
65
+ 2.times { @tm.start ; sleep 0.05 ; @tm.stop }
66
+ @tm.min.must_be_close_to(0.05, 0.01)
67
+ end
68
+
69
+ it "keeps track of the max value" do
70
+ 2.times { @tm.start ; sleep 0.05 ; @tm.stop }
71
+ @tm.max.must_be_close_to(0.05, 0.01)
72
+ end
73
+
74
+ it "keeps track of the sum value" do
75
+ 2.times { @tm.start ; sleep 0.05 ; @tm.stop }
76
+ @tm.sum.must_be_close_to(0.10, 0.01)
77
+ end
78
+
79
+ it "keeps track of the sum of squars value" do
80
+ 3.times { @tm.start ; sleep 0.05 ; @tm.stop }
81
+ @tm.sumsq.must_be_close_to(0.0075)
82
+ end
83
+
84
+ it "keeps track of the minimum start time of all the intervals" do
85
+ f1 = Time.now.gmtime.to_f * 1_000_000
86
+ 5.times { @tm.start ; sleep 0.05 ; @tm.stop }
87
+ f2 = Time.now.gmtime.to_f * 1_000_000
88
+ @tm.sampling_start_time.must_be :>=, f1
89
+ @tm.sampling_start_time.must_be :<, f2
90
+ # distance from now to start time should be greater than the distance from
91
+ # the start to the min start_time
92
+ (f2 - @tm.sampling_start_time).must_be :>, ( @tm.sampling_start_time - f1 )
93
+ end
94
+
95
+ it "keeps track of the last stop time of all the intervals" do
96
+ f1 = Time.now.gmtime.to_f * 1_000_000
97
+ sleep 0.01
98
+ 5.times { @tm.start ; sleep 0.05 ; @tm.stop }
99
+ sleep 0.01
100
+ f2 = Time.now.gmtime.to_f * 1_000_000
101
+ @tm.sampling_stop_time.must_be :>, f1
102
+ @tm.sampling_stop_time.must_be :<=, f2
103
+ # distance from now to max stop time time should be less than the distance
104
+ # from the start to the max stop time
105
+ (f2 - @tm.sampling_stop_time).must_be :<, ( @tm.sampling_stop_time - f1 )
106
+ end
107
+
108
+ it "can create an already running timer" do
109
+ t = Hitimes::TimedMetric.now( 'already-running' )
110
+ t.running?.must_equal true
111
+ end
112
+
113
+ it "can measure a block of code from an instance" do
114
+ t = Hitimes::TimedMetric.new( 'measure a block' )
115
+ 3.times { t.measure { sleep 0.05 } }
116
+ t.duration.must_be_close_to(0.15, 0.01)
117
+ t.count.must_equal 3
118
+ end
119
+
120
+ it "returns the value of the block when measuring" do
121
+ t = Hitimes::TimedMetric.new( 'measure a block' )
122
+ x = t.measure { sleep 0.05; 42 }
123
+ t.duration.must_be_close_to(0.05, 0.002)
124
+ x.must_equal 42
125
+ end
126
+
127
+ describe "#to_hash" do
128
+
129
+ it "has name value" do
130
+ h = @tm.to_hash
131
+ h['name'].must_equal "test-timed-metric"
132
+ end
133
+
134
+ it "has an empty hash for additional_data" do
135
+ h = @tm.to_hash
136
+ h['additional_data'].must_equal Hash.new
137
+ h['additional_data'].size.must_equal 0
138
+ end
139
+
140
+ it "has the right sum" do
141
+ 10.times { |x| @tm.measure { sleep 0.01*x } }
142
+ h = @tm.to_hash
143
+ h['sum'].must_be_close_to(0.45, 0.01)
144
+ end
145
+
146
+ fields = ::Hitimes::Stats::STATS.dup + %w[ name additional_data sampling_start_time sampling_stop_time ]
147
+ fields.each do |f|
148
+ it "has a value for #{f}" do
149
+ @tm.measure { sleep 0.001 }
150
+ h = @tm.to_hash
151
+ h[f].wont_be_nil
152
+ end
153
+ end
154
+ end
155
+ end