hitimes 1.0.4-x86-mswin32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/HISTORY +60 -0
  2. data/LICENSE +13 -0
  3. data/README +134 -0
  4. data/Rakefile +66 -0
  5. data/examples/benchmarks.rb +113 -0
  6. data/examples/stats.rb +31 -0
  7. data/ext/hitimes/extconf.rb +17 -0
  8. data/ext/hitimes/hitimes_ext.c +21 -0
  9. data/ext/hitimes/hitimes_instant_clock_gettime.c +28 -0
  10. data/ext/hitimes/hitimes_instant_osx.c +16 -0
  11. data/ext/hitimes/hitimes_instant_windows.c +27 -0
  12. data/ext/hitimes/hitimes_interval.c +362 -0
  13. data/ext/hitimes/hitimes_interval.h +73 -0
  14. data/ext/hitimes/hitimes_stats.c +269 -0
  15. data/ext/hitimes/hitimes_stats.h +30 -0
  16. data/gemspec.rb +60 -0
  17. data/lib/hitimes.rb +31 -0
  18. data/lib/hitimes/1.8/hitimes_ext.so +0 -0
  19. data/lib/hitimes/1.9/hitimes_ext.so +0 -0
  20. data/lib/hitimes/metric.rb +112 -0
  21. data/lib/hitimes/mutexed_stats.rb +28 -0
  22. data/lib/hitimes/paths.rb +53 -0
  23. data/lib/hitimes/stats.rb +54 -0
  24. data/lib/hitimes/timed_metric.rb +177 -0
  25. data/lib/hitimes/timed_value_metric.rb +235 -0
  26. data/lib/hitimes/value_metric.rb +72 -0
  27. data/lib/hitimes/version.rb +57 -0
  28. data/spec/interval_spec.rb +133 -0
  29. data/spec/metric_spec.rb +30 -0
  30. data/spec/mutex_stats_spec.rb +34 -0
  31. data/spec/paths_spec.rb +13 -0
  32. data/spec/spec_helper.rb +5 -0
  33. data/spec/stats_spec.rb +100 -0
  34. data/spec/timed_metric_spec.rb +155 -0
  35. data/spec/timed_value_metric_spec.rb +172 -0
  36. data/spec/value_metric_spec.rb +110 -0
  37. data/spec/version_spec.rb +33 -0
  38. data/tasks/announce.rake +42 -0
  39. data/tasks/config.rb +108 -0
  40. data/tasks/distribution.rake +77 -0
  41. data/tasks/documentation.rake +32 -0
  42. data/tasks/extension.rake +92 -0
  43. data/tasks/rspec.rake +31 -0
  44. data/tasks/rubyforge.rake +55 -0
  45. data/tasks/utils.rb +80 -0
  46. metadata +150 -0
@@ -0,0 +1,72 @@
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
+ require 'hitimes'
8
+ module Hitimes
9
+ #
10
+ # A ValueMetric holds the data from measuring a single value over a period of
11
+ # time. In most cases this may be a single measurement at a single point in
12
+ # time.
13
+ #
14
+ # A good example of a ValueMetric is measuring the number of items in a queue.
15
+ #
16
+ # A ValueMetric contains a Stats object, therefore ValueMetric has +count+, +max+,
17
+ # +mean+, +min+, +stddev+, +sum+, +sumsq+ methods that delegate to that Stats
18
+ # object for convenience.
19
+ #
20
+ class ValueMetric < Metric
21
+
22
+ # holds all the statistics
23
+ attr_reader :stats
24
+
25
+ #
26
+ # :call-seq:
27
+ # ValueMetric.new( 'my_metric' ) -> ValueMetric
28
+ # ValueMetric.new( 'my_metric', 'foo' => 'bar', 'this' => 42 ) -> ValueMetric
29
+ #
30
+ # Create a new ValueMetric giving it a name and additional data.
31
+ # +additional_data+ may be anything that follows the +to_hash+ protocol.
32
+ #
33
+ def initialize( name, additional_data = {} )
34
+ super( name, additional_data )
35
+ @stats = Stats.new
36
+ end
37
+
38
+ #
39
+ # :call-seq:
40
+ # metric.measure( value ) -> Float
41
+ #
42
+ # Give the +value+ as the measurement to the metric. The value is returned
43
+ #
44
+ def measure( value )
45
+ @sampling_start_time ||= self.utc_microseconds()
46
+ @sampling_start_interval ||= Interval.now
47
+
48
+ @stats.update( value )
49
+
50
+ # update the length of time we have been sampling
51
+ @sampling_delta = @sampling_start_interval.duration_so_far
52
+ end
53
+
54
+ #
55
+ # :call-seq:
56
+ # metric.to_hash -> Hash
57
+ #
58
+ # Convert the metric to a hash
59
+ #
60
+ def to_hash
61
+ h = super
62
+ (Stats::STATS - %w[ rate ]).each do |s|
63
+ h[s] = self.send( s )
64
+ end
65
+ return h
66
+ end
67
+
68
+ # forward appropriate calls directly to the stats object
69
+ extend Forwardable
70
+ def_delegators :@stats, :count, :sum, :max, :mean, :min, :stddev, :sum, :sumsq
71
+ end
72
+ end
@@ -0,0 +1,57 @@
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 version number
13
+ MAJOR = 1
14
+
15
+ # Minor version number
16
+ MINOR = 0
17
+
18
+ # Build number
19
+ BUILD = 4
20
+
21
+ #
22
+ # :call-seq:
23
+ # Version.to_a -> [ MAJOR, MINOR, BUILD ]
24
+ #
25
+ # Return the version as an array of Integers
26
+ #
27
+ def self.to_a
28
+ [MAJOR, MINOR, BUILD]
29
+ end
30
+
31
+ #
32
+ # :call-seq:
33
+ # Version.to_s -> "MAJOR.MINOR.BUILD"
34
+ #
35
+ # Return the version as a String with dotted notation
36
+ #
37
+ def self.to_s
38
+ to_a.join(".")
39
+ end
40
+
41
+ #
42
+ # :call-seq:
43
+ # Version.to_hash -> { :major => ..., :minor => ..., :build => ... }
44
+ #
45
+ # Return the version as a Hash
46
+ #
47
+ def self.to_hash
48
+ { :major => MAJOR, :minor => MINOR, :build => BUILD }
49
+ end
50
+
51
+ # The Version in MAJOR.MINOR.BUILD dotted notation
52
+ STRING = Version.to_s
53
+ end
54
+
55
+ # The Version in MAJOR.MINOR.BUILD dotted notation
56
+ VERSION = Version.to_s
57
+ end
@@ -0,0 +1,133 @@
1
+ require File.expand_path( File.join( File.dirname( __FILE__ ), "spec_helper.rb" ) )
2
+
3
+ require 'hitimes'
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 "duration does not change after stop is calledd" do
89
+ i = Hitimes::Interval.new
90
+ i.start
91
+ x = i.stop
92
+ y = i.duration
93
+ i.stop.should == false
94
+
95
+ z = i.duration
96
+
97
+ x.should == y
98
+ x.should == z
99
+
100
+ y.should == z
101
+ end
102
+
103
+ it "can return how much time has elapsed from the start without stopping the interval" do
104
+ i = Hitimes::Interval.new
105
+ i.start
106
+ x = i.duration_so_far
107
+ i.should be_running
108
+ y = i.duration_so_far
109
+ i.stop
110
+ x.should < y
111
+ x.should < i.duration
112
+ y.should < i.duration
113
+ end
114
+
115
+ describe "#split" do
116
+
117
+ it "creates a new Interval object" do
118
+ i = Hitimes::Interval.new
119
+ i.start
120
+ i2 = i.split
121
+ i.object_id.should_not == i2.object_id
122
+ end
123
+
124
+ it "with the stop instant equivialent to the previous Interval's start instant" do
125
+ i = Hitimes::Interval.new
126
+ i.start
127
+ i2 = i.split
128
+ i.stop_instant.should == i2.start_instant
129
+ end
130
+ end
131
+
132
+ end
133
+
@@ -0,0 +1,30 @@
1
+ require File.expand_path( File.join( File.dirname( __FILE__ ), "spec_helper.rb" ) )
2
+
3
+ require 'hitimes/metric'
4
+
5
+ describe Hitimes::Metric do
6
+ before( :each ) do
7
+ @metric = Hitimes::Metric.new( "testing" )
8
+ end
9
+
10
+ it 'has a name' do
11
+ @metric.name.should == "testing"
12
+ end
13
+
14
+ it "has associated data from initialization" do
15
+ m = Hitimes::Metric.new( "more-data", 'foo' => 'bar', 'this' => 'that' )
16
+ m.additional_data['foo'].should == 'bar'
17
+ m.additional_data['this'].should == 'that'
18
+
19
+ m = Hitimes::Metric.new( "more-data", { 'foo' => 'bar', 'this' => 'that' } )
20
+ m.additional_data['foo'].should == 'bar'
21
+ m.additional_data['this'].should == 'that'
22
+ end
23
+
24
+ it "initially has no sampling times" do
25
+ @metric.sampling_start_time.should == nil
26
+ @metric.sampling_stop_time.should == nil
27
+ end
28
+ end
29
+
30
+
@@ -0,0 +1,34 @@
1
+ require File.expand_path( File.join( File.dirname( __FILE__ ), "spec_helper.rb" ) )
2
+
3
+ require 'hitimes'
4
+ require 'hitimes/mutexed_stats'
5
+
6
+ describe Hitimes::MutexedStats do
7
+ before( :each ) do
8
+ @threads = 5
9
+ @iters = 10_000
10
+ @final_value = @threads * @iters
11
+ end
12
+
13
+ def run_with_scissors( stats, threads, iters )
14
+ spool = []
15
+ threads.times do |t|
16
+ spool << Thread.new { iters.times{ stats.update( 1 ) } }
17
+ end
18
+ spool.each { |t| t.join }
19
+ return stats
20
+ end
21
+
22
+ it "is unsafe normally" do
23
+ pending "not for MRI -- not interruptable in this C extension" do
24
+ stats = run_with_scissors( ::Hitimes::Stats.new, @threads, @iters )
25
+ stats.count.should_not == @final_value
26
+ end
27
+ end
28
+
29
+ it "has a threadsafe update" do
30
+ stats = run_with_scissors( ::Hitimes::MutexedStats.new, @threads, @iters )
31
+ stats.count.should == @final_value
32
+ end
33
+
34
+ end
@@ -0,0 +1,13 @@
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
+ end
@@ -0,0 +1,5 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+
4
+ $: << File.expand_path(File.join(File.dirname(__FILE__),"..","lib"))
5
+
@@ -0,0 +1,100 @@
1
+ require File.expand_path( File.join( File.dirname( __FILE__ ), "spec_helper.rb" ) )
2
+
3
+ require 'hitimes/stats'
4
+ require 'json'
5
+
6
+ describe Hitimes::Stats do
7
+ before( :each ) do
8
+ @stats = Hitimes::Stats.new
9
+ @full_stats = Hitimes::Stats.new
10
+
11
+ [ 1, 2, 3].each { |i| @full_stats.update( i ) }
12
+ end
13
+
14
+ it "is initialized with 0 values" do
15
+ @stats.count.should == 0
16
+ @stats.min.should == 0.0
17
+ @stats.max.should == 0.0
18
+ @stats.sum.should == 0.0
19
+ @stats.rate.should == 0.0
20
+ end
21
+
22
+ it "calculates the mean correctly" do
23
+ @full_stats.mean.should == 2.0
24
+ end
25
+
26
+ it "calculates the rate correctly" do
27
+ @full_stats.rate.should == 0.5
28
+ end
29
+
30
+ it "tracks the maximum value" do
31
+ @full_stats.max.should == 3.0
32
+ end
33
+
34
+ it "tracks the minimum value" do
35
+ @full_stats.min.should == 1.0
36
+ end
37
+
38
+ it "tracks the count" do
39
+ @full_stats.count.should == 3
40
+ end
41
+
42
+ it "tracks the sum" do
43
+ @full_stats.sum.should == 6.0
44
+ end
45
+
46
+ it "calculates the standard deviation" do
47
+ @full_stats.stddev.should == 1.0
48
+ end
49
+
50
+ it "calculates the sum of squares " do
51
+ @full_stats.sumsq.should == 14.0
52
+ end
53
+
54
+ describe "#to_hash " do
55
+ it "converts to a Hash" do
56
+ h = @full_stats.to_hash
57
+ h.size.should == ::Hitimes::Stats::STATS.size
58
+ h.keys.sort.should == ::Hitimes::Stats::STATS
59
+ end
60
+
61
+ it "converts to a limited Hash if given arguments" do
62
+ h = @full_stats.to_hash( "min", "max", "mean" )
63
+ h.size.should == 3
64
+ h.keys.sort.should == %w[ max mean min ]
65
+
66
+ h = @full_stats.to_hash( %w[ count rate ] )
67
+ h.size.should == 2
68
+ h.keys.sort.should == %w[ count rate ]
69
+ end
70
+
71
+ it "raises NoMethodError if an invalid stat is used" do
72
+ lambda { @full_stats.to_hash( "wibble" ) }.should raise_error( NoMethodError )
73
+ end
74
+ end
75
+
76
+ describe "#to_json" do
77
+ it "converts to a json string" do
78
+ j = @full_stats.to_json
79
+ h = JSON.parse( j )
80
+ h.size.should == ::Hitimes::Stats::STATS.size
81
+ h.keys.sort.should == ::Hitimes::Stats::STATS
82
+ end
83
+
84
+ it "converts to a limited Hash if given arguments" do
85
+ j = @full_stats.to_json( "min", "max", "mean" )
86
+ h = JSON.parse( j )
87
+ h.size.should == 3
88
+ h.keys.sort.should == %w[ max mean min ]
89
+
90
+ j = @full_stats.to_json( %w[ count rate ] )
91
+ h = JSON.parse( j )
92
+ h.size.should == 2
93
+ h.keys.sort.should == %w[ count rate ]
94
+ end
95
+
96
+ it "raises NoMethodError if an invalid stat is used" do
97
+ lambda { @full_stats.to_json( "wibble" ) }.should raise_error( NoMethodError )
98
+ end
99
+ end
100
+ end