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,16 @@
1
+ package hitimes;
2
+
3
+ import java.io.IOException;
4
+
5
+ import org.jruby.Ruby;
6
+
7
+ import org.jruby.runtime.load.BasicLibraryService;
8
+
9
+ public class HitimesService implements BasicLibraryService {
10
+ public boolean basicLoad( final Ruby runtime ) throws IOException {
11
+ Hitimes.createHitimesModule( runtime );
12
+ return true;
13
+ }
14
+ }
15
+
16
+
@@ -0,0 +1,112 @@
1
+ package hitimes;
2
+
3
+ import org.jruby.Ruby;
4
+ import org.jruby.RubyClass;
5
+ import org.jruby.RubyObject;
6
+
7
+ import org.jruby.RubyNumeric;
8
+ import org.jruby.runtime.builtin.IRubyObject;
9
+ import org.jruby.runtime.ObjectAllocator;
10
+
11
+ import org.jruby.anno.JRubyMethod;
12
+ import org.jruby.anno.JRubyClass;
13
+
14
+ @JRubyClass( name = "Hitimes::Stats" )
15
+ public class HitimesStats extends RubyObject {
16
+
17
+ private double min = 0.0;
18
+ private double max = 0.0;
19
+ private double sum = 0.0;
20
+ private double sumsq = 0.0;
21
+ private long count = 0;
22
+
23
+ public static final ObjectAllocator ALLOCATOR = new ObjectAllocator() {
24
+ public IRubyObject allocate(Ruby runtime, RubyClass klass) {
25
+ return new HitimesStats( runtime, klass );
26
+ }
27
+ };
28
+
29
+ public HitimesStats( Ruby runtime, RubyClass klass ) {
30
+ super( runtime, klass );
31
+ }
32
+
33
+ @JRubyMethod( name = "update", required = 1, argTypes = RubyNumeric.class )
34
+ public IRubyObject update( IRubyObject val ) {
35
+ double v = RubyNumeric.num2dbl( val );
36
+
37
+ if ( 0 == this.count ) {
38
+ this.min = this.max = v;
39
+ } else {
40
+ this.min = ( v < this.min ) ? v : this.min;
41
+ this.max = ( v > this.max ) ? v : this.max;
42
+ }
43
+
44
+ this.count += 1;
45
+ this.sum += v;
46
+ this.sumsq += (v * v);
47
+
48
+ return val;
49
+ }
50
+
51
+ @JRubyMethod( name = "mean" )
52
+ public IRubyObject mean() {
53
+ double mean = 0.0;
54
+
55
+ if ( this.count > 0 ) {
56
+ mean = this.sum / this.count;
57
+ }
58
+
59
+ return getRuntime().newFloat( mean );
60
+ }
61
+
62
+
63
+ @JRubyMethod( name = "rate" )
64
+ public IRubyObject rate() {
65
+ double rate = 0.0;
66
+
67
+ if ( this.sum > 0.0 ) {
68
+ rate = this.count / this.sum ;
69
+ }
70
+
71
+ return getRuntime().newFloat( rate );
72
+ }
73
+
74
+ @JRubyMethod( name = "stddev" )
75
+ public IRubyObject stddev() {
76
+ double stddev = 0.0;
77
+
78
+ if ( this.count > 1 ) {
79
+ double sq_sum = this.sum * this.sum;
80
+ stddev = Math.sqrt( ( this.sumsq - ( sq_sum / this.count ) ) / ( this.count - 1 ) );
81
+ }
82
+ return getRuntime().newFloat( stddev );
83
+ }
84
+
85
+
86
+ @JRubyMethod( name = "min" )
87
+ public IRubyObject min() {
88
+ return getRuntime().newFloat( this.min );
89
+ }
90
+
91
+ @JRubyMethod( name = "max" )
92
+ public IRubyObject max() {
93
+ return getRuntime().newFloat( this.max );
94
+ }
95
+
96
+ @JRubyMethod( name = "sum" )
97
+ public IRubyObject sum() {
98
+ return getRuntime().newFloat( this.sum );
99
+ }
100
+
101
+ @JRubyMethod( name = "sumsq" )
102
+ public IRubyObject sumsq() {
103
+ return getRuntime().newFloat( this.sumsq );
104
+ }
105
+
106
+ @JRubyMethod( name = "count" )
107
+ public IRubyObject count() {
108
+ return getRuntime().newFixnum( this.count );
109
+ }
110
+ }
111
+
112
+
@@ -0,0 +1,66 @@
1
+ #--
2
+ # Copyright (c) 2008 Jeremy Hinegardner
3
+ # All rights reserved. See LICENSE and/or COPYING for details.
4
+ #++
5
+
6
+ #
7
+ # The top level module containing the contents of the hitimes library
8
+ #
9
+ # use the library with:
10
+ #
11
+ # require 'hitimes'
12
+ #
13
+ module Hitimes
14
+ #
15
+ # Base class of all errors in Hitimes
16
+ #
17
+ class Error < ::StandardError; end
18
+
19
+ # Hitimes.measure { } -> Float
20
+ #
21
+ # Times the execution of the block, returning the number of seconds it took
22
+ def self.measure(&block)
23
+ Hitimes::Interval.measure(&block)
24
+ end
25
+ end
26
+ require 'hitimes/paths'
27
+ require 'hitimes/version'
28
+
29
+ # Load the binary extension, try loading one for the specific version of ruby
30
+ # and if that fails, then fall back to one in the top of the library.
31
+ # this is the method recommended by rake-compiler
32
+
33
+ attempts = [
34
+ "hitimes/#{RUBY_VERSION.sub(/\.\d+$/,'')}/hitimes",
35
+ "hitimes/hitimes"
36
+ ]
37
+ loaded = false
38
+
39
+ path_exceptions = []
40
+ attempts.each do |path|
41
+ begin
42
+ require path
43
+ loaded = true
44
+ break
45
+ rescue LoadError => load_error
46
+ full_path = File.expand_path(path)
47
+ path_exceptions << [ full_path, load_error.message ]
48
+ end
49
+ end
50
+
51
+ if !loaded then
52
+ msg = ["Unable to find binary extension, was hitimes installed correctly? The following paths were tried."]
53
+ path_exceptions.each do |path, message|
54
+ msg << "#{path} : #{message}"
55
+ end
56
+ raise LoadError, msg.join("\n")
57
+ end
58
+
59
+ require 'hitimes/stats'
60
+ require 'hitimes/mutexed_stats'
61
+
62
+ require 'hitimes/metric'
63
+ require 'hitimes/value_metric'
64
+ require 'hitimes/timed_metric'
65
+ require 'hitimes/timed_value_metric'
66
+
@@ -0,0 +1,118 @@
1
+
2
+ #--
3
+ # Copyright (c) 2008, 2009 Jeremy Hinegardner
4
+ # All rights reserved. See LICENSE and/or COPYING for details.
5
+ #++
6
+
7
+ module Hitimes
8
+ #
9
+ # Metric hold the common meta information for all derived metric classes
10
+ #
11
+ # All metrics hold the meta information of:
12
+ #
13
+ # * The name of the metric
14
+ # * The time of day the first measurement is taken
15
+ # * The time of day the last measurement is taken
16
+ # * additional data
17
+ #
18
+ # Each derived class is assumed to set the sampling_start_time and
19
+ # sampling_stop_time appropriately.
20
+ #
21
+ # Metric itself should generally not be used. Only use the derived classes.
22
+ #
23
+ class Metric
24
+
25
+ # the number of seconds as a float since the sampling_start_time
26
+ attr_reader :sampling_delta
27
+
28
+ # An additional hash of data to associate with the metric
29
+ attr_reader :additional_data
30
+
31
+ # The 'name' to associate with the metric
32
+ attr_reader :name
33
+
34
+ #
35
+ # :call-seq:
36
+ # Metric.new( 'my_metric' ) -> Metric
37
+ # Metric.new( 'my_metric', 'foo' => 'bar', 'this' => 42 ) -> Metric
38
+ #
39
+ # Create a new ValueMetric giving it a name and additional data.
40
+ #
41
+ # +additional_data+ may be anything that follows the +to_hash+ protocol.
42
+ # +name+ may be anything that follows the +to_s+ protocol.
43
+ #
44
+ def initialize( name, additional_data = {} )
45
+ @sampling_start_time = nil
46
+ @sampling_start_interval = nil
47
+ @sampling_delta = 0
48
+
49
+ @name = name.to_s
50
+ @additional_data = additional_data.to_hash
51
+ end
52
+
53
+ #
54
+ # :call-seq:
55
+ # metric.sampling_start_time -> Float or nil
56
+ #
57
+ # The time at which the first sample was taken.
58
+ # This is the number of microseconds since UNIX epoch UTC as a Float
59
+ #
60
+ # If the metric has not started measuring then the start time is nil.
61
+ #
62
+ def sampling_start_time
63
+ if @sampling_start_interval then
64
+ @sampling_start_time ||= self.utc_microseconds()
65
+ else
66
+ nil
67
+ end
68
+ end
69
+
70
+ #
71
+ # :call-seq:
72
+ # metric.sampling_stop_time -> Float or nil
73
+ #
74
+ # The time at which the last sample was taken
75
+ # This is the number of microseconds since UNIX epoch UTC as a Float
76
+ #
77
+ # If the metric has not completely measured at least one thing then
78
+ # stop time is nil.
79
+ #
80
+ # Because accessing the actual 'time of day' is an expesive operation, we
81
+ # only get the time of day at the beginning of the first measurement and we
82
+ # keep track of the offset from that point in @sampling_delta.
83
+ #
84
+ # When sampling_stop_time is called, the actual time of day is caculated.
85
+ #
86
+ def sampling_stop_time
87
+ if @sampling_delta > 0 then
88
+ (self.sampling_start_time + (@sampling_delta * 1_000_000))
89
+ else
90
+ nil
91
+ end
92
+ end
93
+
94
+ #
95
+ # :call-seq:
96
+ # metric.to_hash -> Hash
97
+ # metric.to_hash
98
+ #
99
+ # Convert the metric to a Hash.
100
+ #
101
+ def to_hash
102
+ { 'sampling_start_time' => self.sampling_start_time,
103
+ 'sampling_stop_time' => self.sampling_stop_time,
104
+ 'additional_data' => self.additional_data,
105
+ 'name' => self.name }
106
+ end
107
+
108
+ #
109
+ # :call-seq:
110
+ # metric.utc_microseconds -> Float
111
+ #
112
+ # The current time in microseconds from the UNIX Epoch in the UTC
113
+ #
114
+ def utc_microseconds
115
+ Time.now.gmtime.to_f * 1_000_000
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,32 @@
1
+ #--
2
+ # Copyright (c) 2008, 2009 Jeremy Hinegardner
3
+ # All rights reserved. See LICENSE and/or COPYING for details.
4
+ #++
5
+
6
+ require 'thread'
7
+
8
+ module Hitimes
9
+ #
10
+ # MutexedStats is the start of a threadsafe Stats class. Currently, on MRI
11
+ # Ruby the Stats object is already threadsafe, so there is no need to use
12
+ # MutexedStats.
13
+ #
14
+ class MutexedStats < Stats
15
+ def initialize
16
+ @mutex = Mutex.new
17
+ end
18
+
19
+ # call-seq:
20
+ # mutex_stat.update( val ) -> nil
21
+ #
22
+ # Update the running stats with the new value in a threadsafe manner.
23
+ #
24
+ def update( value )
25
+ @mutex.synchronize do
26
+ super( value )
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+
@@ -0,0 +1,53 @@
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
+ # Access to various paths inside the project programatically
9
+ #
10
+ module Paths
11
+ #
12
+ # :call-seq:
13
+ # Hitimes::Paths.root_dir -> String
14
+ #
15
+ # Returns The full expanded path of the parent directory of +lib+
16
+ # going up the path from the current file. A trailing File::SEPARATOR
17
+ # is guaranteed.
18
+ #
19
+ def self.root_dir
20
+ @root_dir ||=(
21
+ path_parts = ::File.expand_path(__FILE__).split(::File::SEPARATOR)
22
+ lib_index = path_parts.rindex("lib")
23
+ @root_dir = path_parts[0...lib_index].join(::File::SEPARATOR) + ::File::SEPARATOR
24
+ )
25
+ end
26
+
27
+ #
28
+ # :call-seq:
29
+ # Hitimes::Paths.lib_path( *args ) -> String
30
+ #
31
+ # Returns The full expanded path of the +lib+ directory below
32
+ # _root_dir_. All parameters passed in are joined onto the
33
+ # result. A trailing File::SEPARATOR is guaranteed if
34
+ # _args_ are *not* present.
35
+ #
36
+ def self.lib_path(*args)
37
+ self.sub_path("lib", *args)
38
+ end
39
+
40
+ #
41
+ # :call-seq:
42
+ # Hitimes::Paths.sub_path( sub, *args ) -> String
43
+ #
44
+ # Returns the full expanded path of the +sub+ directory below _root_dir. All
45
+ # _arg_ parameters passed in are joined onto the result. A trailing
46
+ # File::SEPARATOR is guaranteed if _args_ are *not* present.
47
+ #
48
+ def self.sub_path(sub,*args)
49
+ sp = ::File.join(root_dir, sub) + File::SEPARATOR
50
+ sp = ::File.join(sp, *args) if args
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,58 @@
1
+ #--
2
+ # Copyright (c) 2008, 2009 Jeremy Hinegardner
3
+ # All rights reserved. See LICENSE and/or COPYING for details.
4
+ #++
5
+
6
+ require 'stringio'
7
+ module Hitimes
8
+ class Stats
9
+ # A list of the available stats
10
+ STATS = %w[ count max mean min rate stddev sum sumsq ]
11
+
12
+ #
13
+ # call-seq:
14
+ # stat.to_hash -> Hash
15
+ # stat.to_hash( %w[ count max mean ]) -> Hash
16
+ #
17
+ # return a hash of the stats. By default this returns a hash of all stats
18
+ # but passing in an array of items will limit the stats returned to only
19
+ # those in the Array.
20
+ #
21
+ # If passed in an empty array or nil to to_hash then STATS is assumed to be
22
+ # the list of stats to return in the hash.
23
+ #
24
+ def to_hash( *args )
25
+ h = {}
26
+ args = [ args ].flatten
27
+ args = STATS if args.empty?
28
+ args.each do |meth|
29
+ h[meth] = self.send( meth )
30
+ end
31
+ return h
32
+ end
33
+
34
+ #
35
+ # call-seq:
36
+ # stat.to_json -> String
37
+ # stat.to_json( *args ) -> String
38
+ #
39
+ # return a json string of the stats. By default this returns a json string
40
+ # of all the stats. If an array of items is passed in, those that match the
41
+ # known stats will be all that is included in the json output.
42
+ #
43
+ def to_json( *args )
44
+ h = to_hash( *args )
45
+ a = []
46
+ s = StringIO.new
47
+
48
+ s.print "{ "
49
+ h.each_pair do |k,v|
50
+ a << "\"#{k}\": #{v}"
51
+ end
52
+ s.print a.join(", ")
53
+ s.print "}"
54
+ return s.string
55
+ end
56
+
57
+ end
58
+ end