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,73 @@
1
+ /**
2
+ * Copyright (c) 2008 Jeremy Hinegardner
3
+ * All rights reserved. See LICENSE and/or COPYING for details.
4
+ *
5
+ * vim: shiftwidth=4
6
+ */
7
+
8
+ #ifndef __HITIMES_INTERVAL_H__
9
+ #define __HITIMES_INTERVAL_H__
10
+
11
+ #include <ruby.h>
12
+
13
+ #define NANOSECONDS_PER_SECOND 1e9l
14
+
15
+ #ifdef USE_INSTANT_CLOCK_GETTIME
16
+ # define HITIMES_U64INT unsigned long long int
17
+ # define HITIMES_INSTANT_CONVERSION_FACTOR 1e9l
18
+ #elif USE_INSTANT_OSX
19
+ # define HITIMES_U64INT uint64_t
20
+ # define HITIMES_INSTANT_CONVERSION_FACTOR hitimes_instant_conversion_factor()
21
+ #elif USE_INSTANT_WINDOWS
22
+ # define HITIMES_U64INT unsigned __int64
23
+ # define HITIMES_INSTANT_CONVERSION_FACTOR hitimes_instant_conversion_factor()
24
+ #else
25
+ # error "Unable to build hitimes, no Instance backend available"
26
+ #endif
27
+
28
+
29
+ /* an alias for a 64bit unsigned integer. The various sytem dependenent
30
+ * files must define hitimes_u64int_t
31
+ */
32
+ typedef HITIMES_U64INT hitimes_instant_t;
33
+
34
+ typedef struct hitimes_interval {
35
+ hitimes_instant_t start_instant;
36
+ hitimes_instant_t stop_instant;
37
+ long double duration;
38
+ } hitimes_interval_t;
39
+
40
+ /* all the backends must define these methods */
41
+ hitimes_instant_t hitimes_get_current_instant( );
42
+ long double hitimes_instant_conversion_factor( );
43
+
44
+ /* init methods */
45
+ void Init_hitimes_stats();
46
+ void Init_hitimes_interval();
47
+
48
+
49
+ /* Module and Classes -- defined at the top level */
50
+ extern VALUE mH; /* module Hitimes */
51
+ extern VALUE eH_Error; /* class Hitimes::Error */
52
+ extern VALUE cH_Interval; /* class Hitimes::Interval */
53
+
54
+
55
+ /**
56
+ * Methods for Interval
57
+ */
58
+
59
+ VALUE hitimes_interval_free(hitimes_interval_t* i) ;
60
+ VALUE hitimes_interval_alloc(VALUE klass);
61
+ VALUE hitimes_interval_now( );
62
+ VALUE hitimes_interval_measure( );
63
+ VALUE hitimes_interval_split( VALUE self );
64
+ VALUE hitimes_interval_start( VALUE self );
65
+ VALUE hitimes_interval_stop( VALUE self );
66
+ VALUE hitimes_interval_started( VALUE self );
67
+ VALUE hitimes_interval_stopped( VALUE self );
68
+ VALUE hitimes_interval_running( VALUE self );
69
+ VALUE hitimes_interval_start_instant( VALUE self );
70
+ VALUE hitimes_interval_stop_instant( VALUE self );
71
+ VALUE hitimes_interval_duration ( VALUE self );
72
+
73
+ #endif
@@ -0,0 +1,269 @@
1
+ /**
2
+ * Copyright (c) 2008 Jeremy Hinegardner
3
+ * All rights reserved. See LICENSE and/or COPYING for details.
4
+ *
5
+ * vim: shiftwidth=4
6
+ */
7
+
8
+ #include "hitimes_stats.h"
9
+
10
+ /* classes defined here */
11
+ VALUE cH_Stats; /* Hitimes::Stats */
12
+
13
+ /**
14
+ * Allocator and Deallocator for Stats classes
15
+ */
16
+
17
+ VALUE hitimes_stats_free(hitimes_stats_t* s)
18
+ {
19
+ xfree( s );
20
+ return Qnil;
21
+ }
22
+
23
+ VALUE hitimes_stats_alloc(VALUE klass)
24
+ {
25
+ VALUE obj;
26
+ hitimes_stats_t* s = xmalloc( sizeof( hitimes_stats_t ) );
27
+
28
+ s->min = 0.0;
29
+ s->max = 0.0;
30
+ s->count = 0;
31
+ s->sum = 0.0;
32
+ s->sumsq = 0.0;
33
+
34
+ obj = Data_Wrap_Struct(klass, NULL, hitimes_stats_free, s);
35
+
36
+ return obj;
37
+ }
38
+
39
+
40
+ /**
41
+ * call-seq:
42
+ * stat.update( val ) -> val
43
+ *
44
+ * Update the running stats with the new value.
45
+ * Return the input value.
46
+ */
47
+ VALUE hitimes_stats_update( VALUE self, VALUE v )
48
+ {
49
+ long double new_v;
50
+ hitimes_stats_t *stats;
51
+
52
+ Data_Get_Struct( self, hitimes_stats_t, stats );
53
+ new_v = NUM2DBL( v );
54
+
55
+ if ( 0 == stats->count ) {
56
+ stats->min = new_v;
57
+ stats->max = new_v;
58
+ } else {
59
+ stats->min = ( new_v < stats->min) ? ( new_v ) : ( stats->min );
60
+ stats->max = ( new_v > stats->max) ? ( new_v ) : ( stats->max );
61
+ }
62
+
63
+ stats->count += 1;
64
+ stats->sum += new_v;
65
+ stats->sumsq += ( new_v * new_v );
66
+
67
+ return v;
68
+ }
69
+
70
+ /**
71
+ * call-seq:
72
+ * stat.mean -> Float
73
+ *
74
+ * Return the arithmetic mean of the values put into the Stats object. If no
75
+ * values have passed through the stats object then 0.0 is returned;
76
+ */
77
+ VALUE hitimes_stats_mean( VALUE self )
78
+ {
79
+ hitimes_stats_t *stats;
80
+ long double mean = 0.0;
81
+
82
+ Data_Get_Struct( self, hitimes_stats_t, stats );
83
+
84
+ if ( stats->count > 0 ) {
85
+ mean = stats->sum / stats->count ;
86
+ }
87
+
88
+ return rb_float_new( mean );
89
+ }
90
+
91
+
92
+ /**
93
+ * call-seq:
94
+ * stat.rate -> Float
95
+ *
96
+ * Return the +count+ divided by +sum+.
97
+ *
98
+ * In many cases when Stats#update( _value_ ) is called, the _value_ is a unit
99
+ * of time, typically seconds or microseconds. #rate is a convenience for those
100
+ * times. In this case, where _value_ is a unit if time, then count divided by
101
+ * sum is a useful value, i.e. +something per unit of time+.
102
+ *
103
+ * In the case where _value_ is a non-time related value, then the value
104
+ * returned by _rate_ is not really useful.
105
+ *
106
+ */
107
+ VALUE hitimes_stats_rate( VALUE self )
108
+ {
109
+ hitimes_stats_t *stats;
110
+ long double rate = 0.0;
111
+
112
+ Data_Get_Struct( self, hitimes_stats_t, stats );
113
+
114
+ if ( stats->sum > 0.0 ) {
115
+ rate = stats->count / stats->sum;
116
+ }
117
+
118
+ return rb_float_new( rate );
119
+ }
120
+
121
+
122
+ /**
123
+ * call-seq:
124
+ * stat.max -> Float
125
+ *
126
+ * Return the maximum value that has passed through the Stats object
127
+ */
128
+ VALUE hitimes_stats_max( VALUE self )
129
+ {
130
+ hitimes_stats_t *stats;
131
+
132
+ Data_Get_Struct( self, hitimes_stats_t, stats );
133
+
134
+ return rb_float_new( stats->max );
135
+ }
136
+
137
+
138
+
139
+ /**
140
+ * call-seq:
141
+ * stat.min -> Float
142
+ *
143
+ * Return the minimum value that has passed through the Stats object
144
+ */
145
+ VALUE hitimes_stats_min( VALUE self )
146
+ {
147
+ hitimes_stats_t *stats;
148
+
149
+ Data_Get_Struct( self, hitimes_stats_t, stats );
150
+
151
+ return rb_float_new( stats->min );
152
+ }
153
+
154
+
155
+ /**
156
+ * call-seq:
157
+ * stat.count -> Integer
158
+ *
159
+ * Return the number of values that have passed through the Stats object.
160
+ */
161
+ VALUE hitimes_stats_count( VALUE self )
162
+ {
163
+ hitimes_stats_t *stats;
164
+
165
+ Data_Get_Struct( self, hitimes_stats_t, stats );
166
+
167
+ return LONG2NUM( stats->count );
168
+ }
169
+
170
+
171
+ /**
172
+ * call-seq:
173
+ * stat.sum -> Float
174
+ *
175
+ * Return the sum of all the values that have passed through the Stats object.
176
+ */
177
+ VALUE hitimes_stats_sum( VALUE self )
178
+ {
179
+ hitimes_stats_t *stats;
180
+
181
+ Data_Get_Struct( self, hitimes_stats_t, stats );
182
+
183
+ return rb_float_new( stats->sum );
184
+ }
185
+
186
+ /**
187
+ * call-seq:
188
+ * stat.sumsq -> Float
189
+ *
190
+ * Return the sum of the squars of all the values that passed through the Stats
191
+ * object.
192
+ */
193
+ VALUE hitimes_stats_sumsq( VALUE self )
194
+ {
195
+ hitimes_stats_t *stats;
196
+
197
+ Data_Get_Struct( self, hitimes_stats_t, stats );
198
+
199
+ return rb_float_new( stats->sumsq );
200
+ }
201
+
202
+
203
+ /**
204
+ * call-seq:
205
+ * stat.stddev -> Float
206
+ *
207
+ * Return the standard deviation of all the values that have passed through the
208
+ * Stats object. The standard deviation has no meaning unless the count is > 1,
209
+ * therefore if the current _stat.count_ is < 1 then 0.0 will be returned;
210
+ */
211
+ VALUE hitimes_stats_stddev ( VALUE self )
212
+ {
213
+ hitimes_stats_t *stats;
214
+ long double stddev = 0.0;
215
+
216
+ Data_Get_Struct( self, hitimes_stats_t, stats );
217
+ if ( stats->count > 1 ) {
218
+ stddev = sqrt( ( stats->sumsq - ( stats->sum * stats->sum / stats->count ) ) / ( stats->count - 1 ) );
219
+ }
220
+
221
+ return rb_float_new( stddev );
222
+ }
223
+
224
+
225
+ /**
226
+ * Document-class: Hitimes::Stats
227
+ *
228
+ * The Stats class encapulsates capturing and reporting statistics. It is
229
+ * modeled after the RFuzz::Sampler class, but implemented in C. For general use
230
+ * you allocate a new Stats object, and then update it with new values. The
231
+ * Stats object will keep track of the _min_, _max_, _count_, _sum_ and _sumsq_
232
+ * and when you want you may also retrieve the _mean_, _stddev_ and _rate_.
233
+ *
234
+ * this contrived example shows getting a list of all the files in a directory
235
+ * and running stats on file sizes.
236
+ *
237
+ * s = Hitimes::Stats.new
238
+ * dir = ARGV.shift || Dir.pwd
239
+ * Dir.entries( dir ).each do |entry|
240
+ * fs = File.stat( entry )
241
+ * if fs.file? then
242
+ * s.update( fs.size )
243
+ * end
244
+ * end
245
+ *
246
+ * %w[ count min max mean sum stddev rate ].each do |m|
247
+ * puts "#{m.rjust(6)} : #{s.send( m ) }"
248
+ * end
249
+ */
250
+ void Init_hitimes_stats()
251
+ {
252
+
253
+ mH = rb_define_module("Hitimes");
254
+
255
+ cH_Stats = rb_define_class_under( mH, "Stats", rb_cObject ); /* in hitimes_stats.c */
256
+ rb_define_alloc_func( cH_Stats, hitimes_stats_alloc );
257
+
258
+ rb_define_method( cH_Stats, "update", hitimes_stats_update, 1 ); /* in hitimes_stats.c */
259
+
260
+ rb_define_method( cH_Stats, "count", hitimes_stats_count, 0 ); /* in hitimes_stats.c */
261
+ rb_define_method( cH_Stats, "max", hitimes_stats_max, 0 ); /* in hitimes_stats.c */
262
+ rb_define_method( cH_Stats, "mean", hitimes_stats_mean, 0 ); /* in hitimes_stats.c */
263
+ rb_define_method( cH_Stats, "min", hitimes_stats_min, 0 ); /* in hitimes_stats.c */
264
+ rb_define_method( cH_Stats, "rate", hitimes_stats_rate, 0 ); /* in hitimes_stats.c */
265
+ rb_define_method( cH_Stats, "sum", hitimes_stats_sum, 0 ); /* in hitimes_stats.c */
266
+ rb_define_method( cH_Stats, "sumsq", hitimes_stats_sumsq, 0 ); /* in hitimes_stats.c */
267
+ rb_define_method( cH_Stats, "stddev", hitimes_stats_stddev, 0 ); /* in hitimes_stats.c */
268
+ }
269
+
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Copyright (c) 2008 Jeremy Hinegardner
3
+ * All rights reserved. See LICENSE and/or COPYING for details.
4
+ *
5
+ * vim: shiftwidth=4
6
+ */
7
+
8
+ #ifndef __HITIMES_STATS_H__
9
+ #define __HITIMES_STATS_H__
10
+
11
+ #include <ruby.h>
12
+ #include <math.h>
13
+
14
+ /* classes and modules defined elswhere */
15
+ extern VALUE mH; /* Hitimes */
16
+ extern VALUE eH_Error; /* Hitimes::Error */
17
+ extern VALUE cH_Stats; /* Hitimes::Stats */
18
+
19
+
20
+ typedef struct hitimes_stats {
21
+ long double min;
22
+ long double max;
23
+ long double sum;
24
+ long double sumsq;
25
+ long long count;
26
+ } hitimes_stats_t;
27
+
28
+ #endif
29
+
30
+
@@ -0,0 +1,66 @@
1
+ package hitimes;
2
+
3
+ import java.lang.Math;
4
+ import java.lang.System;
5
+
6
+ import org.jruby.anno.JRubyClass;
7
+ import org.jruby.anno.JRubyMethod;
8
+ import org.jruby.anno.JRubyModule;
9
+ import org.jruby.anno.JRubyConstant;
10
+ import org.jruby.runtime.Visibility;
11
+
12
+ import org.jruby.Ruby;
13
+ import org.jruby.RubyClass;
14
+ import org.jruby.RubyException;
15
+ import org.jruby.RubyModule;
16
+ import org.jruby.RubyObject;
17
+
18
+ import org.jruby.exceptions.RaiseException;
19
+
20
+ import org.jruby.runtime.builtin.IRubyObject;
21
+
22
+
23
+ /**
24
+ * @author <a href="mailto:jeremy@hinegardner.org">Jeremy Hinegardner</a>
25
+ */
26
+ @JRubyModule( name = "Hitimes" )
27
+ public class Hitimes {
28
+
29
+ public static final double INSTANT_CONVERSION_FACTOR = 1000000000d;
30
+
31
+ private static final Ruby __ruby__ = Ruby.getGlobalRuntime();
32
+
33
+ public static RubyClass hitimesIntervalClass;
34
+ /**
35
+ * Create the Hitimes module and add it to the Ruby runtime.
36
+ */
37
+ public static RubyModule createHitimesModule( Ruby runtime ) {
38
+ RubyModule mHitimes = runtime.defineModule("Hitimes");
39
+ mHitimes.defineConstant("INSTANT_CONVERSION_FACTOR", __ruby__.newFloat(INSTANT_CONVERSION_FACTOR));
40
+ mHitimes.defineAnnotatedMethods( Hitimes.class );
41
+
42
+ RubyClass cStandardError = runtime.getStandardError();
43
+ RubyClass cHitimesError = mHitimes.defineClassUnder("Error", cStandardError, cStandardError.getAllocator());
44
+
45
+ RubyClass cHitimesStats = mHitimes.defineClassUnder("Stats", runtime.getObject(), HitimesStats.ALLOCATOR );
46
+ cHitimesStats.defineAnnotatedMethods( HitimesStats.class );
47
+
48
+ RubyClass cHitimesInterval = mHitimes.defineClassUnder("Interval", runtime.getObject(), HitimesInterval.ALLOCATOR );
49
+ Hitimes.hitimesIntervalClass = cHitimesInterval;
50
+ cHitimesInterval.defineAnnotatedMethods( HitimesInterval.class );
51
+
52
+ return mHitimes;
53
+ }
54
+
55
+ static RaiseException newHitimesError( Ruby runtime, String message ) {
56
+ RubyClass errorClass = runtime.getModule("Hitimes").getClass( "Error" );
57
+ return new RaiseException( RubyException.newException( runtime, errorClass, message ), true );
58
+ }
59
+
60
+
61
+ @JRubyMethod( name = "raw_instant", module = true )
62
+ public static IRubyObject rawInstant(IRubyObject self) {
63
+ return __ruby__.newFixnum( System.nanoTime() );
64
+ }
65
+
66
+ }
@@ -0,0 +1,176 @@
1
+ package hitimes;
2
+
3
+ import org.jruby.runtime.builtin.IRubyObject;
4
+
5
+ import org.jruby.Ruby;
6
+ import org.jruby.RubyClass;
7
+ import org.jruby.RubyObject;
8
+
9
+ import org.jruby.runtime.Block;
10
+ import org.jruby.runtime.ObjectAllocator;
11
+ import org.jruby.runtime.ThreadContext;
12
+
13
+ import org.jruby.anno.JRubyClass;
14
+ import org.jruby.anno.JRubyMethod;
15
+
16
+ @JRubyClass( name = "Hitimes::Interval" )
17
+ public class HitimesInterval extends RubyObject {
18
+
19
+ private static final long INSTANT_NOT_SET = Long.MIN_VALUE;
20
+ private static final double DURATION_NOT_SET = Double.NaN;
21
+
22
+ public static final ObjectAllocator ALLOCATOR = new ObjectAllocator() {
23
+ public IRubyObject allocate(Ruby runtime, RubyClass klass) {
24
+ return new HitimesInterval( runtime, klass );
25
+ }
26
+ };
27
+
28
+ public HitimesInterval( Ruby runtime, RubyClass klass ) {
29
+ super( runtime, klass );
30
+ }
31
+
32
+ public HitimesInterval( Ruby runtime, RubyClass klass, long start ) {
33
+ super( runtime, klass );
34
+ this.start_instant = start;
35
+ }
36
+
37
+
38
+ private long start_instant = INSTANT_NOT_SET;
39
+ private long stop_instant = INSTANT_NOT_SET;
40
+ private double duration = DURATION_NOT_SET;
41
+
42
+ @JRubyMethod( name = "duration", alias = { "length", "to_f", "to_seconds" } )
43
+ public IRubyObject duration() {
44
+
45
+ /*
46
+ * if start has not yet been called, then raise an exception.
47
+ */
48
+ if ( INSTANT_NOT_SET == this.start_instant ) {
49
+ throw Hitimes.newHitimesError( getRuntime(), "Attempt to report a duration on an interval that has not started");
50
+ }
51
+
52
+ /*
53
+ * if stop has not yet been called, then return the amount of time so far
54
+ */
55
+ if ( INSTANT_NOT_SET == this.stop_instant ) {
56
+ double d = ( System.nanoTime() - this.start_instant ) / Hitimes.INSTANT_CONVERSION_FACTOR;
57
+ return getRuntime().newFloat( d );
58
+ }
59
+
60
+ /*
61
+ * if stop has been called, then calculate the duration and return
62
+ */
63
+ if ( DURATION_NOT_SET == this.duration ) {
64
+ this.duration = (this.stop_instant - this.start_instant) / Hitimes.INSTANT_CONVERSION_FACTOR;
65
+ }
66
+
67
+ return getRuntime().newFloat( this.duration );
68
+
69
+ }
70
+
71
+ @JRubyMethod( name = "duration_so_far" )
72
+ public IRubyObject duration_so_far() {
73
+ IRubyObject rc = getRuntime().getFalse();
74
+
75
+ if ( INSTANT_NOT_SET == this.start_instant ) {
76
+ return rc;
77
+ }
78
+
79
+ if ( INSTANT_NOT_SET == this.stop_instant ) {
80
+ double d = ( System.nanoTime() - this.start_instant ) / Hitimes.INSTANT_CONVERSION_FACTOR;
81
+ return getRuntime().newFloat( d );
82
+ }
83
+
84
+ return rc;
85
+ }
86
+
87
+ @JRubyMethod( name = "started?" )
88
+ public IRubyObject is_started() {
89
+ if ( INSTANT_NOT_SET == this.start_instant ) {
90
+ return getRuntime().getFalse();
91
+ }
92
+ return getRuntime().getTrue();
93
+ }
94
+
95
+ @JRubyMethod( name = "running?" )
96
+ public IRubyObject is_running() {
97
+ if ( ( INSTANT_NOT_SET != this.start_instant ) && ( INSTANT_NOT_SET == this.stop_instant ) ) {
98
+ return getRuntime().getTrue();
99
+ }
100
+ return getRuntime().getFalse();
101
+ }
102
+
103
+ @JRubyMethod( name = "stopped?" )
104
+ public IRubyObject is_stopped() {
105
+ if ( INSTANT_NOT_SET == this.stop_instant ) {
106
+ return getRuntime().getFalse();
107
+ }
108
+ return getRuntime().getTrue();
109
+ }
110
+
111
+ @JRubyMethod( name = "start_instant" )
112
+ public IRubyObject start_instant() {
113
+ return getRuntime().newFixnum( this.start_instant );
114
+ }
115
+
116
+ @JRubyMethod( name = "stop_instant" )
117
+ public IRubyObject stop_instant() {
118
+ return getRuntime().newFixnum( this.stop_instant );
119
+ }
120
+
121
+ @JRubyMethod( name = "start" )
122
+ public IRubyObject start() {
123
+ if ( INSTANT_NOT_SET == this.start_instant ) {
124
+ this.start_instant = System.nanoTime();
125
+ return getRuntime().getTrue();
126
+ }
127
+ return getRuntime().getFalse();
128
+ }
129
+
130
+ @JRubyMethod( name = "stop" )
131
+ public IRubyObject stop() {
132
+ if ( INSTANT_NOT_SET == this.start_instant ) {
133
+ throw Hitimes.newHitimesError( getRuntime(), "Attempt to stop an interval that has not started" );
134
+ }
135
+
136
+ if ( INSTANT_NOT_SET == this.stop_instant ) {
137
+ this.stop_instant = System.nanoTime();
138
+ this.duration = (this.stop_instant - this.start_instant) / Hitimes.INSTANT_CONVERSION_FACTOR;
139
+ return getRuntime().newFloat( this.duration );
140
+ }
141
+
142
+ return getRuntime().getFalse();
143
+ }
144
+
145
+ @JRubyMethod( name = "split" )
146
+ public IRubyObject split() {
147
+ this.stop();
148
+ return new HitimesInterval( getRuntime(), Hitimes.hitimesIntervalClass, this.stop_instant );
149
+ }
150
+
151
+ @JRubyMethod( name = "now", module = true )
152
+ public static IRubyObject now( IRubyObject self ) {
153
+ return new HitimesInterval( self.getRuntime(), Hitimes.hitimesIntervalClass, System.nanoTime() );
154
+ }
155
+
156
+ @JRubyMethod( name = "measure", module = true, frame = true )
157
+ public static IRubyObject measure( IRubyObject self, Block block ) {
158
+
159
+ Ruby runtime = self.getRuntime();
160
+
161
+ if ( block.isGiven() ) {
162
+ IRubyObject nil = runtime.getNil();
163
+ ThreadContext context = runtime.getCurrentContext();
164
+
165
+ HitimesInterval interval = new HitimesInterval( runtime, Hitimes.hitimesIntervalClass );
166
+
167
+ interval.start();
168
+ block.yield( context, nil );
169
+ interval.stop();
170
+
171
+ return interval.duration();
172
+ } else {
173
+ throw Hitimes.newHitimesError( runtime, "No block given to Interval.measure" );
174
+ }
175
+ }
176
+ }