hitimes 1.3.0-x64-mingw32

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.
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