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.
- checksums.yaml +7 -0
- data/CONTRIBUTING.md +57 -0
- data/HISTORY.md +124 -0
- data/LICENSE +16 -0
- data/Manifest.txt +44 -0
- data/README.md +200 -0
- data/Rakefile +28 -0
- data/examples/benchmarks.rb +113 -0
- data/examples/stats.rb +31 -0
- data/ext/hitimes/c/extconf.rb +24 -0
- data/ext/hitimes/c/hitimes.c +37 -0
- data/ext/hitimes/c/hitimes_instant_clock_gettime.c +28 -0
- data/ext/hitimes/c/hitimes_instant_osx.c +45 -0
- data/ext/hitimes/c/hitimes_instant_windows.c +27 -0
- data/ext/hitimes/c/hitimes_interval.c +370 -0
- data/ext/hitimes/c/hitimes_interval.h +73 -0
- data/ext/hitimes/c/hitimes_stats.c +269 -0
- data/ext/hitimes/c/hitimes_stats.h +30 -0
- data/ext/hitimes/java/src/hitimes/Hitimes.java +66 -0
- data/ext/hitimes/java/src/hitimes/HitimesInterval.java +176 -0
- data/ext/hitimes/java/src/hitimes/HitimesService.java +16 -0
- data/ext/hitimes/java/src/hitimes/HitimesStats.java +112 -0
- data/lib/hitimes.rb +66 -0
- data/lib/hitimes/2.0/hitimes.so +0 -0
- data/lib/hitimes/2.1/hitimes.so +0 -0
- data/lib/hitimes/2.2/hitimes.so +0 -0
- data/lib/hitimes/2.3/hitimes.so +0 -0
- data/lib/hitimes/2.4/hitimes.so +0 -0
- data/lib/hitimes/2.5/hitimes.so +0 -0
- data/lib/hitimes/metric.rb +118 -0
- data/lib/hitimes/mutexed_stats.rb +32 -0
- data/lib/hitimes/paths.rb +53 -0
- data/lib/hitimes/stats.rb +58 -0
- data/lib/hitimes/timed_metric.rb +176 -0
- data/lib/hitimes/timed_value_metric.rb +233 -0
- data/lib/hitimes/value_metric.rb +71 -0
- data/lib/hitimes/version.rb +8 -0
- data/spec/hitimes_spec.rb +24 -0
- data/spec/interval_spec.rb +136 -0
- data/spec/metric_spec.rb +28 -0
- data/spec/mutex_stats_spec.rb +36 -0
- data/spec/paths_spec.rb +11 -0
- data/spec/spec_helper.rb +11 -0
- data/spec/stats_spec.rb +98 -0
- data/spec/timed_metric_spec.rb +155 -0
- data/spec/timed_value_metric_spec.rb +171 -0
- data/spec/value_metric_spec.rb +108 -0
- data/spec/version_spec.rb +7 -0
- data/tasks/default.rake +242 -0
- data/tasks/extension.rake +38 -0
- data/tasks/this.rb +208 -0
- 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
|
+
}
|