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
data/Rakefile
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# vim: syntax=ruby
|
2
|
+
load 'tasks/this.rb'
|
3
|
+
|
4
|
+
This.name = "hitimes"
|
5
|
+
This.author = "Jeremy Hinegardner"
|
6
|
+
This.email = "jeremy@copiousfreetime.org"
|
7
|
+
This.homepage = "http://github.com/copiousfreetime/#{ This.name }"
|
8
|
+
|
9
|
+
This.ruby_gemspec do |spec|
|
10
|
+
spec.add_development_dependency( 'rake' , '~> 12.0')
|
11
|
+
spec.add_development_dependency( 'minitest' , '~> 5.5' )
|
12
|
+
spec.add_development_dependency( 'rdoc' , '~> 5.0' )
|
13
|
+
spec.add_development_dependency( 'json' , '~> 2.0' )
|
14
|
+
spec.add_development_dependency( 'rake-compiler', '~> 1.0' )
|
15
|
+
spec.add_development_dependency( 'rake-compiler-dock', '~> 0.6' )
|
16
|
+
spec.add_development_dependency( 'simplecov' , '~> 0.14' )
|
17
|
+
|
18
|
+
spec.extensions.concat This.extension_conf_files
|
19
|
+
spec.license = "ISC"
|
20
|
+
end
|
21
|
+
|
22
|
+
This.java_gemspec( This.ruby_gemspec ) do |spec|
|
23
|
+
spec.extensions.clear
|
24
|
+
spec.files << "lib/hitimes/hitimes.jar"
|
25
|
+
end
|
26
|
+
|
27
|
+
load 'tasks/default.rake'
|
28
|
+
load 'tasks/extension.rake'
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
require 'time'
|
3
|
+
|
4
|
+
#
|
5
|
+
# this is all here in case this example is run from the examples directory
|
6
|
+
#
|
7
|
+
begin
|
8
|
+
require 'hitimes'
|
9
|
+
rescue LoadError => le
|
10
|
+
ext_path = File.expand_path( File.join( File.dirname( __FILE__ ), "..", "ext" ) )
|
11
|
+
lib_path = File.expand_path( File.join( File.dirname( __FILE__ ), "..", "lib" ) )
|
12
|
+
if $:.include?( ext_path ) then
|
13
|
+
raise le
|
14
|
+
end
|
15
|
+
$: << ext_path
|
16
|
+
$: << lib_path
|
17
|
+
retry
|
18
|
+
end
|
19
|
+
|
20
|
+
#----------------------------------------------------------------------
|
21
|
+
# test program to look at the performance sampling time durations using
|
22
|
+
# different methods
|
23
|
+
#----------------------------------------------------------------------
|
24
|
+
|
25
|
+
include Benchmark
|
26
|
+
|
27
|
+
#
|
28
|
+
# Normal apprach to Interval usage
|
29
|
+
#
|
30
|
+
def hitimes_duration_i1
|
31
|
+
i = Hitimes::Interval.new
|
32
|
+
i.start
|
33
|
+
i.stop
|
34
|
+
end
|
35
|
+
|
36
|
+
#
|
37
|
+
# Use the easy access method to start stop an interval
|
38
|
+
#
|
39
|
+
def hitimes_duration_i2
|
40
|
+
Hitimes::Interval.now.stop
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
# Use a new timer each time
|
45
|
+
#
|
46
|
+
def hitimes_duration_t1
|
47
|
+
Hitimes::TimedMetric.now('duration_t1').stop
|
48
|
+
end
|
49
|
+
|
50
|
+
#
|
51
|
+
# reuse the same timer over and over
|
52
|
+
#
|
53
|
+
HT2= Hitimes::TimedMetric.new( 'duration_t2' )
|
54
|
+
def hitimes_duration_t2
|
55
|
+
HT2.start
|
56
|
+
HT2.stop
|
57
|
+
end
|
58
|
+
|
59
|
+
HT3 = Hitimes::TimedMetric.new( 'duration_t3' )
|
60
|
+
def hitimes_duration_t3
|
61
|
+
HT3.measure { nil }
|
62
|
+
end
|
63
|
+
|
64
|
+
#
|
65
|
+
# Check out the speed of the TimedValueMetric too
|
66
|
+
#
|
67
|
+
def hitimes_duration_tv1
|
68
|
+
Hitimes::TimedValueMetric.now( 'duration_tv1' ).stop( 42 )
|
69
|
+
end
|
70
|
+
|
71
|
+
HTV2 = Hitimes::TimedValueMetric.new( 'duration_tv2' )
|
72
|
+
def hitimes_duration_tv2
|
73
|
+
HTV2.start
|
74
|
+
HTV2.stop( 42 )
|
75
|
+
end
|
76
|
+
|
77
|
+
HTV3 = Hitimes::TimedValueMetric.new( 'duration_tv3' )
|
78
|
+
def hitimes_duration_tv3
|
79
|
+
HTV3.measure( 42 ) { nil }
|
80
|
+
end
|
81
|
+
|
82
|
+
#
|
83
|
+
# use the Struct::Tms values and return the difference in User time between 2
|
84
|
+
# successive calls
|
85
|
+
#
|
86
|
+
def process_duration
|
87
|
+
t1 = Process.times.utime
|
88
|
+
Process.times.utime - t1
|
89
|
+
end
|
90
|
+
|
91
|
+
#
|
92
|
+
# Take 2 times and subtract one from the other
|
93
|
+
#
|
94
|
+
def time_duration
|
95
|
+
t1 = Time.now.to_f
|
96
|
+
Time.now.to_f - t1
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
puts "Testing time sampling 100,000 times"
|
101
|
+
|
102
|
+
bm(30) do |x|
|
103
|
+
x.report("Process") { 100_000.times { process_duration } }
|
104
|
+
x.report("Time") { 100_000.times { time_duration } }
|
105
|
+
x.report("Hitimes::TimedMetric 1") { 100_000.times { hitimes_duration_t1 } }
|
106
|
+
x.report("Hitimes::TimedMetric 2") { 100_000.times { hitimes_duration_t2 } }
|
107
|
+
x.report("Hitimes::TimedMetric 3") { 100_000.times { hitimes_duration_t3 } }
|
108
|
+
x.report("Hitimes::Interval 1") { 100_000.times { hitimes_duration_i1 } }
|
109
|
+
x.report("Hitimes::Interval 2") { 100_000.times { hitimes_duration_i2 } }
|
110
|
+
x.report("Hitimes::TimedValueMetric 1") { 100_000.times { hitimes_duration_tv1 } }
|
111
|
+
x.report("Hitimes::TimedValueMetric 2") { 100_000.times { hitimes_duration_tv2 } }
|
112
|
+
x.report("Hitimes::TimedValueMetric 3") { 100_000.times { hitimes_duration_tv3 } }
|
113
|
+
end
|
data/examples/stats.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
#
|
2
|
+
# this is all here in case this example is run from the examples directory
|
3
|
+
#
|
4
|
+
begin
|
5
|
+
require 'hitimes'
|
6
|
+
rescue LoadError => le
|
7
|
+
%w[ ext lib ].each do |p|
|
8
|
+
path = File.expand_path( File.join( File.dirname( __FILE__ ), "..", p ) )
|
9
|
+
if $:.include?( path ) then
|
10
|
+
raise le
|
11
|
+
end
|
12
|
+
$: << path
|
13
|
+
end
|
14
|
+
retry
|
15
|
+
end
|
16
|
+
|
17
|
+
s = Hitimes::Stats.new
|
18
|
+
dir = ARGV.shift || Dir.pwd
|
19
|
+
Dir.entries( dir ).each do |entry|
|
20
|
+
fs = File.stat( entry )
|
21
|
+
if fs.file? then
|
22
|
+
s.update( fs.size )
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
Hitimes::Stats::STATS.each do |m|
|
27
|
+
puts "#{m.rjust(6)} : #{s.send( m ) }"
|
28
|
+
end
|
29
|
+
|
30
|
+
puts s.to_hash.inspect
|
31
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'rbconfig'
|
2
|
+
require 'mkmf'
|
3
|
+
|
4
|
+
if RbConfig::CONFIG['host_os'] =~ /darwin/ then
|
5
|
+
$CFLAGS += " -DUSE_INSTANT_OSX=1 -Wall"
|
6
|
+
$LDFLAGS += " -framework CoreServices"
|
7
|
+
elsif RbConfig::CONFIG['host_os'] =~ /win(32|64)/ or RbConfig::CONFIG['host_os'] =~ /mingw/ then
|
8
|
+
$CFLAGS += " -DUSE_INSTANT_WINDOWS=1"
|
9
|
+
else
|
10
|
+
if have_library("rt", "clock_gettime") then
|
11
|
+
$CFLAGS += " -DUSE_INSTANT_CLOCK_GETTIME=1"
|
12
|
+
elsif have_library("c", "clock_gettime") then
|
13
|
+
$CFLAGS += " -DUSE_INSTANT_CLOCK_GETTIME=1"
|
14
|
+
else
|
15
|
+
raise NotImplementedError, <<-_
|
16
|
+
Unable to find the function 'clock_gettime' in either libc or librt.
|
17
|
+
Please file an issue at https://github.com/copiousfreetime/hitimes.
|
18
|
+
_
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# put in a different location if on windows so we can have fat binaries
|
23
|
+
subdir = RUBY_VERSION.gsub(/\.\d+$/,'')
|
24
|
+
create_makefile("hitimes/#{subdir}/hitimes")
|
@@ -0,0 +1,37 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#include "hitimes_interval.h"
|
3
|
+
|
4
|
+
/* Module and Classes */
|
5
|
+
VALUE mH; /* module Hitimes */
|
6
|
+
VALUE eH_Error; /* class Hitimes::Error */
|
7
|
+
|
8
|
+
|
9
|
+
/**
|
10
|
+
* call-seq:
|
11
|
+
* Hitimes.raw_instant -> Integer
|
12
|
+
*
|
13
|
+
* Return the raw instant value from the operating system
|
14
|
+
*/
|
15
|
+
VALUE hitimes_instant_raw( )
|
16
|
+
{
|
17
|
+
unsigned long long i = (unsigned long long)hitimes_get_current_instant( );
|
18
|
+
|
19
|
+
return ULL2NUM(i);
|
20
|
+
}
|
21
|
+
|
22
|
+
/*
|
23
|
+
* Document-class: Hitimes::Error
|
24
|
+
*
|
25
|
+
* General error class for the Hitimes module
|
26
|
+
*/
|
27
|
+
void Init_hitimes( )
|
28
|
+
{
|
29
|
+
mH = rb_define_module("Hitimes");
|
30
|
+
|
31
|
+
eH_Error = rb_define_class_under(mH, "Error", rb_eStandardError);
|
32
|
+
rb_define_const( mH, "INSTANT_CONVERSION_FACTOR", DBL2NUM( HITIMES_INSTANT_CONVERSION_FACTOR ));
|
33
|
+
rb_define_module_function( mH, "raw_instant", hitimes_instant_raw, 0 );
|
34
|
+
|
35
|
+
Init_hitimes_interval();
|
36
|
+
Init_hitimes_stats( );
|
37
|
+
}
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#ifdef USE_INSTANT_CLOCK_GETTIME
|
2
|
+
|
3
|
+
#include "hitimes_interval.h"
|
4
|
+
|
5
|
+
#include <time.h>
|
6
|
+
#ifndef CLOCK_MONOTONIC
|
7
|
+
# include <sys/time.h>
|
8
|
+
# ifndef CLOCK_MONOTONIC
|
9
|
+
# ifdef __linux__
|
10
|
+
# include <linux/time.h>
|
11
|
+
# endif
|
12
|
+
# endif
|
13
|
+
#endif
|
14
|
+
|
15
|
+
hitimes_instant_t hitimes_get_current_instant( )
|
16
|
+
{
|
17
|
+
struct timespec time;
|
18
|
+
int rc;
|
19
|
+
|
20
|
+
rc = clock_gettime( CLOCK_MONOTONIC, &time);
|
21
|
+
if ( 0 != rc ) {
|
22
|
+
char* e = strerror( rc );
|
23
|
+
rb_raise(eH_Error, "Unable to retrieve time for CLOCK_MONOTONIC : %s", e );
|
24
|
+
}
|
25
|
+
|
26
|
+
return ( ( NANOSECONDS_PER_SECOND * (long)time.tv_sec ) + time.tv_nsec );
|
27
|
+
}
|
28
|
+
#endif
|
@@ -0,0 +1,45 @@
|
|
1
|
+
#ifdef USE_INSTANT_OSX
|
2
|
+
|
3
|
+
#include "hitimes_interval.h"
|
4
|
+
#include <mach/mach.h>
|
5
|
+
#include <mach/mach_time.h>
|
6
|
+
|
7
|
+
/* All this OSX code is adapted from http://developer.apple.com/library/mac/#qa/qa1398/_index.html */
|
8
|
+
|
9
|
+
/*
|
10
|
+
* returns the conversion factor, this value is used to convert
|
11
|
+
* the value from hitimes_get_current_instant() into seconds
|
12
|
+
*/
|
13
|
+
long double hitimes_instant_conversion_factor()
|
14
|
+
{
|
15
|
+
static mach_timebase_info_data_t s_timebase_info;
|
16
|
+
static long double conversion_factor;
|
17
|
+
static uint64_t nano_conversion;
|
18
|
+
|
19
|
+
/**
|
20
|
+
* If this is the first time we've run, get the timebase.
|
21
|
+
* We can use denom == 0 to indicate that s_timebase_info is
|
22
|
+
* uninitialised because it makes no sense to have a zero
|
23
|
+
* denominator is a fraction.
|
24
|
+
*/
|
25
|
+
|
26
|
+
if ( s_timebase_info.denom == 0 ) {
|
27
|
+
mach_timebase_info(&s_timebase_info);
|
28
|
+
nano_conversion = s_timebase_info.numer / s_timebase_info.denom;
|
29
|
+
conversion_factor = (long double) (nano_conversion) * (1e9l);
|
30
|
+
}
|
31
|
+
|
32
|
+
return conversion_factor;
|
33
|
+
}
|
34
|
+
|
35
|
+
/*
|
36
|
+
* returns the mach absolute time, which has no meaning outside of a conversion
|
37
|
+
* factor.
|
38
|
+
*/
|
39
|
+
hitimes_instant_t hitimes_get_current_instant()
|
40
|
+
{
|
41
|
+
return mach_absolute_time();
|
42
|
+
}
|
43
|
+
|
44
|
+
|
45
|
+
#endif
|
@@ -0,0 +1,27 @@
|
|
1
|
+
#ifdef USE_INSTANT_WINDOWS
|
2
|
+
|
3
|
+
#include "hitimes_interval.h"
|
4
|
+
|
5
|
+
|
6
|
+
/*
|
7
|
+
* returns the conversion factor, this value is used to convert
|
8
|
+
* the value from hitimes_get_current_instant() into seconds
|
9
|
+
*/
|
10
|
+
long double hitimes_instant_conversion_factor()
|
11
|
+
{
|
12
|
+
LARGE_INTEGER ticks_per_second;
|
13
|
+
QueryPerformanceFrequency( &ticks_per_second );
|
14
|
+
return (double)ticks_per_second.QuadPart;
|
15
|
+
}
|
16
|
+
|
17
|
+
/*
|
18
|
+
* returns the number of ticks
|
19
|
+
*/
|
20
|
+
hitimes_instant_t hitimes_get_current_instant()
|
21
|
+
{
|
22
|
+
LARGE_INTEGER tick;
|
23
|
+
QueryPerformanceCounter(&tick);
|
24
|
+
return (hitimes_instant_t)tick.QuadPart;
|
25
|
+
}
|
26
|
+
|
27
|
+
#endif
|
@@ -0,0 +1,370 @@
|
|
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_interval.h"
|
9
|
+
|
10
|
+
/* Modules and Classes -- defined here */
|
11
|
+
VALUE cH_Interval; /* class Hitimes::Interval */
|
12
|
+
|
13
|
+
/**
|
14
|
+
* Allocator and Deallocator for Interval classes
|
15
|
+
*/
|
16
|
+
|
17
|
+
VALUE hitimes_interval_free(hitimes_interval_t* i)
|
18
|
+
{
|
19
|
+
xfree( i );
|
20
|
+
return Qnil;
|
21
|
+
}
|
22
|
+
|
23
|
+
VALUE hitimes_interval_alloc(VALUE klass)
|
24
|
+
{
|
25
|
+
VALUE obj;
|
26
|
+
hitimes_interval_t* i = xmalloc( sizeof( hitimes_interval_t ) );
|
27
|
+
|
28
|
+
i->start_instant = 0L;
|
29
|
+
i->stop_instant = 0L;
|
30
|
+
i->duration = -1.0l;
|
31
|
+
|
32
|
+
obj = Data_Wrap_Struct(klass, NULL, hitimes_interval_free, i);
|
33
|
+
return obj;
|
34
|
+
}
|
35
|
+
|
36
|
+
/**
|
37
|
+
* call-seq:
|
38
|
+
* Interval.now -> Interval
|
39
|
+
*
|
40
|
+
* Create an interval that has already started
|
41
|
+
*/
|
42
|
+
VALUE hitimes_interval_now( )
|
43
|
+
{
|
44
|
+
VALUE obj;
|
45
|
+
hitimes_interval_t *i = xmalloc( sizeof( hitimes_interval_t ) );
|
46
|
+
|
47
|
+
i->start_instant = hitimes_get_current_instant( );
|
48
|
+
i->stop_instant = 0L;
|
49
|
+
i->duration = -1.0l;
|
50
|
+
|
51
|
+
obj = Data_Wrap_Struct(cH_Interval, NULL, hitimes_interval_free, i);
|
52
|
+
|
53
|
+
return obj;
|
54
|
+
}
|
55
|
+
|
56
|
+
/**
|
57
|
+
* call-seq:
|
58
|
+
* Interval.measure { } -> Float
|
59
|
+
*
|
60
|
+
* Times the execution of the block returning the number of seconds it took
|
61
|
+
*/
|
62
|
+
VALUE hitimes_interval_measure( )
|
63
|
+
{
|
64
|
+
hitimes_instant_t before;
|
65
|
+
hitimes_instant_t after;
|
66
|
+
long double duration;
|
67
|
+
|
68
|
+
if ( !rb_block_given_p() ) {
|
69
|
+
rb_raise(eH_Error, "No block given to Interval.measure" );
|
70
|
+
}
|
71
|
+
|
72
|
+
before = hitimes_get_current_instant( );
|
73
|
+
rb_yield( Qnil );
|
74
|
+
after = hitimes_get_current_instant( );
|
75
|
+
|
76
|
+
duration = ( after - before ) / HITIMES_INSTANT_CONVERSION_FACTOR;
|
77
|
+
return rb_float_new( duration );
|
78
|
+
}
|
79
|
+
|
80
|
+
/**
|
81
|
+
* call-seq:
|
82
|
+
* interval.split -> Interval
|
83
|
+
*
|
84
|
+
* Immediately stop the current interval and start a new interval that has a
|
85
|
+
* start_instant equivalent to the stop_interval of self.
|
86
|
+
*/
|
87
|
+
VALUE hitimes_interval_split( VALUE self )
|
88
|
+
{
|
89
|
+
hitimes_interval_t *first;
|
90
|
+
hitimes_interval_t *second = xmalloc( sizeof( hitimes_interval_t ) );
|
91
|
+
VALUE obj;
|
92
|
+
|
93
|
+
Data_Get_Struct( self, hitimes_interval_t, first );
|
94
|
+
first->stop_instant = hitimes_get_current_instant( );
|
95
|
+
|
96
|
+
second->start_instant = first->stop_instant;
|
97
|
+
second->stop_instant = 0L;
|
98
|
+
second->duration = -1.0l;
|
99
|
+
|
100
|
+
obj = Data_Wrap_Struct(cH_Interval, NULL, hitimes_interval_free, second);
|
101
|
+
|
102
|
+
return obj;
|
103
|
+
}
|
104
|
+
|
105
|
+
|
106
|
+
/**
|
107
|
+
* call-seq:
|
108
|
+
* interval.start -> boolean
|
109
|
+
*
|
110
|
+
* mark the start of the interval. Calling start on an already started
|
111
|
+
* interval has no effect. An interval can only be started once. If the
|
112
|
+
* interval is truely started +true+ is returned otherwise +false+.
|
113
|
+
*/
|
114
|
+
VALUE hitimes_interval_start( VALUE self )
|
115
|
+
{
|
116
|
+
hitimes_interval_t *i;
|
117
|
+
VALUE rc = Qfalse;
|
118
|
+
|
119
|
+
Data_Get_Struct( self, hitimes_interval_t, i );
|
120
|
+
if ( 0L == i->start_instant ) {
|
121
|
+
i->start_instant = hitimes_get_current_instant( );
|
122
|
+
i->stop_instant = 0L;
|
123
|
+
i->duration = -1.0l;
|
124
|
+
|
125
|
+
rc = Qtrue;
|
126
|
+
}
|
127
|
+
|
128
|
+
return rc;
|
129
|
+
}
|
130
|
+
|
131
|
+
|
132
|
+
/**
|
133
|
+
* call-seq:
|
134
|
+
* interval.stop -> bool or Float
|
135
|
+
*
|
136
|
+
* mark the stop of the interval. Calling stop on an already stopped interval
|
137
|
+
* has no effect. An interval can only be stopped once. If the interval is
|
138
|
+
* truely stopped then the duration is returned, otherwise +false+.
|
139
|
+
*/
|
140
|
+
VALUE hitimes_interval_stop( VALUE self )
|
141
|
+
{
|
142
|
+
hitimes_interval_t *i;
|
143
|
+
VALUE rc = Qfalse;
|
144
|
+
|
145
|
+
Data_Get_Struct( self, hitimes_interval_t, i );
|
146
|
+
if ( 0L == i->start_instant ) {
|
147
|
+
rb_raise(eH_Error, "Attempt to stop an interval that has not started" );
|
148
|
+
}
|
149
|
+
|
150
|
+
if ( 0L == i->stop_instant ) {
|
151
|
+
i->stop_instant = hitimes_get_current_instant( );
|
152
|
+
i->duration = ( i->stop_instant - i->start_instant ) / HITIMES_INSTANT_CONVERSION_FACTOR;
|
153
|
+
rc = rb_float_new( i->duration );
|
154
|
+
}
|
155
|
+
|
156
|
+
return rc;
|
157
|
+
}
|
158
|
+
|
159
|
+
/**
|
160
|
+
* call-seq:
|
161
|
+
* interval.duration_so_far -> Float or false
|
162
|
+
*
|
163
|
+
* return how the duration so far. This will return the duration from the time
|
164
|
+
* the Interval was started if the interval is running, otherwise it will return
|
165
|
+
* false.
|
166
|
+
*/
|
167
|
+
VALUE hitimes_interval_duration_so_far( VALUE self )
|
168
|
+
{
|
169
|
+
hitimes_interval_t *i;
|
170
|
+
VALUE rc = Qfalse;
|
171
|
+
|
172
|
+
Data_Get_Struct( self, hitimes_interval_t, i );
|
173
|
+
if ( 0L == i->start_instant ) {
|
174
|
+
return rc;
|
175
|
+
}
|
176
|
+
|
177
|
+
if ( 0L == i->stop_instant ) {
|
178
|
+
long double d;
|
179
|
+
hitimes_instant_t now = hitimes_get_current_instant( );
|
180
|
+
d = ( now - i->start_instant ) / HITIMES_INSTANT_CONVERSION_FACTOR;
|
181
|
+
rc = rb_float_new( d );
|
182
|
+
}
|
183
|
+
return rc;
|
184
|
+
}
|
185
|
+
|
186
|
+
|
187
|
+
/**
|
188
|
+
* call-seq:
|
189
|
+
* interval.started? -> boolean
|
190
|
+
*
|
191
|
+
* returns whether or not the interval has been started
|
192
|
+
*/
|
193
|
+
VALUE hitimes_interval_started( VALUE self )
|
194
|
+
{
|
195
|
+
hitimes_interval_t *i;
|
196
|
+
|
197
|
+
Data_Get_Struct( self, hitimes_interval_t, i );
|
198
|
+
|
199
|
+
return ( 0L == i->start_instant ) ? Qfalse : Qtrue;
|
200
|
+
}
|
201
|
+
|
202
|
+
|
203
|
+
/**
|
204
|
+
* call-seq:
|
205
|
+
* interval.stopped? -> boolean
|
206
|
+
*
|
207
|
+
* returns whether or not the interval has been stopped
|
208
|
+
*/
|
209
|
+
VALUE hitimes_interval_stopped( VALUE self )
|
210
|
+
{
|
211
|
+
hitimes_interval_t *i;
|
212
|
+
|
213
|
+
Data_Get_Struct( self, hitimes_interval_t, i );
|
214
|
+
|
215
|
+
return ( 0L == i->stop_instant ) ? Qfalse : Qtrue;
|
216
|
+
}
|
217
|
+
|
218
|
+
/**
|
219
|
+
* call-seq:
|
220
|
+
* interval.running? -> boolean
|
221
|
+
*
|
222
|
+
* returns whether or not the interval is running or not. This means that it
|
223
|
+
* has started, but not stopped.
|
224
|
+
*/
|
225
|
+
VALUE hitimes_interval_running( VALUE self )
|
226
|
+
{
|
227
|
+
hitimes_interval_t *i;
|
228
|
+
VALUE rc = Qfalse;
|
229
|
+
|
230
|
+
Data_Get_Struct( self, hitimes_interval_t, i );
|
231
|
+
if ( ( 0L != i->start_instant ) && ( 0L == i->stop_instant ) ) {
|
232
|
+
rc = Qtrue;
|
233
|
+
}
|
234
|
+
|
235
|
+
return rc;
|
236
|
+
}
|
237
|
+
|
238
|
+
|
239
|
+
/**
|
240
|
+
* call-seq:
|
241
|
+
* interval.start_instant -> Integer
|
242
|
+
*
|
243
|
+
* The integer representing the start instant of the Interval. This value
|
244
|
+
* is not useful on its own. It is a platform dependent value.
|
245
|
+
*/
|
246
|
+
VALUE hitimes_interval_start_instant( VALUE self )
|
247
|
+
{
|
248
|
+
hitimes_interval_t *i;
|
249
|
+
|
250
|
+
Data_Get_Struct( self, hitimes_interval_t, i );
|
251
|
+
|
252
|
+
return ULL2NUM( i->start_instant );
|
253
|
+
}
|
254
|
+
|
255
|
+
|
256
|
+
/**
|
257
|
+
* call-seq:
|
258
|
+
* interval.stop_instant -> Integer
|
259
|
+
*
|
260
|
+
* The integer representing the stop instant of the Interval. This value
|
261
|
+
* is not useful on its own. It is a platform dependent value.
|
262
|
+
*/
|
263
|
+
VALUE hitimes_interval_stop_instant( VALUE self )
|
264
|
+
{
|
265
|
+
hitimes_interval_t *i;
|
266
|
+
|
267
|
+
Data_Get_Struct( self, hitimes_interval_t, i );
|
268
|
+
|
269
|
+
return ULL2NUM( i->stop_instant );
|
270
|
+
}
|
271
|
+
|
272
|
+
|
273
|
+
|
274
|
+
/**
|
275
|
+
* call-seq:
|
276
|
+
* interval.duration -> Float
|
277
|
+
* interval.to_f -> Float
|
278
|
+
* interval.to_seconds -> Float
|
279
|
+
* interval.length -> Float
|
280
|
+
*
|
281
|
+
* Returns the Float value of the interval, the value is in seconds. If the
|
282
|
+
* interval has not had stop called yet, it will report the number of seconds
|
283
|
+
* in the interval up to the current point in time.
|
284
|
+
*
|
285
|
+
* Raises Error if duration is called on an interval that has not started yet.
|
286
|
+
*/
|
287
|
+
VALUE hitimes_interval_duration ( VALUE self )
|
288
|
+
{
|
289
|
+
hitimes_interval_t *i;
|
290
|
+
|
291
|
+
Data_Get_Struct( self, hitimes_interval_t, i );
|
292
|
+
|
293
|
+
/* raise an error if the internval is not started */
|
294
|
+
if ( 0L == i->start_instant ) {
|
295
|
+
rb_raise(eH_Error, "Attempt to report a duration on an interval that has not started" );
|
296
|
+
}
|
297
|
+
|
298
|
+
|
299
|
+
/**
|
300
|
+
* if stop has not yet been called, then return the amount of time so far
|
301
|
+
*/
|
302
|
+
if ( 0L == i->stop_instant ) {
|
303
|
+
long double d;
|
304
|
+
hitimes_instant_t now = hitimes_get_current_instant( );
|
305
|
+
d = ( now - i->start_instant ) / HITIMES_INSTANT_CONVERSION_FACTOR;
|
306
|
+
return rb_float_new( d );
|
307
|
+
}
|
308
|
+
|
309
|
+
/*
|
310
|
+
* stop has been called, calculate the duration and save the result
|
311
|
+
*/
|
312
|
+
if ( i->duration < 0.0 ) {
|
313
|
+
i->duration = ( i->stop_instant - i->start_instant ) / HITIMES_INSTANT_CONVERSION_FACTOR;
|
314
|
+
}
|
315
|
+
|
316
|
+
return rb_float_new( i->duration );
|
317
|
+
}
|
318
|
+
|
319
|
+
|
320
|
+
/**
|
321
|
+
* Document-class: Hitimes::Interval
|
322
|
+
*
|
323
|
+
* This is the lowest level timing mechanism available. It allows for easy
|
324
|
+
* measuring based upon a block:
|
325
|
+
*
|
326
|
+
* duration = Interval.measure { ... }
|
327
|
+
*
|
328
|
+
* Or measuring something specifically
|
329
|
+
*
|
330
|
+
* interval = Interval.new
|
331
|
+
* interval.start
|
332
|
+
* duration = interval.stop
|
333
|
+
*
|
334
|
+
* Allocating and starting an interval can be done in one method call with
|
335
|
+
*
|
336
|
+
* interval = Interval.now
|
337
|
+
*
|
338
|
+
* Interval is useful when you only need to track a single interval of time, or
|
339
|
+
* if you do not want to track statistics about an operation.
|
340
|
+
*
|
341
|
+
*/
|
342
|
+
void Init_hitimes_interval()
|
343
|
+
{
|
344
|
+
mH = rb_define_module("Hitimes");
|
345
|
+
|
346
|
+
cH_Interval = rb_define_class_under( mH, "Interval", rb_cObject );
|
347
|
+
rb_define_alloc_func( cH_Interval, hitimes_interval_alloc );
|
348
|
+
|
349
|
+
rb_define_module_function( cH_Interval, "now", hitimes_interval_now, 0 ); /* in hitimes_interval.c */
|
350
|
+
rb_define_module_function( cH_Interval, "measure", hitimes_interval_measure, 0 ); /* in hitimes_interval.c */
|
351
|
+
|
352
|
+
rb_define_method( cH_Interval, "duration", hitimes_interval_duration, 0 ); /* in hitimes_interval.c */
|
353
|
+
rb_define_method( cH_Interval, "length", hitimes_interval_duration, 0 );
|
354
|
+
rb_define_method( cH_Interval, "to_f", hitimes_interval_duration, 0 );
|
355
|
+
rb_define_method( cH_Interval, "to_seconds", hitimes_interval_duration, 0 );
|
356
|
+
|
357
|
+
rb_define_method( cH_Interval, "duration_so_far", hitimes_interval_duration_so_far, 0); /* in hitimes_interval.c */
|
358
|
+
|
359
|
+
rb_define_method( cH_Interval, "started?", hitimes_interval_started, 0 ); /* in hitimes_interval.c */
|
360
|
+
rb_define_method( cH_Interval, "running?", hitimes_interval_running, 0 ); /* in hitimes_interval.c */
|
361
|
+
rb_define_method( cH_Interval, "stopped?", hitimes_interval_stopped, 0 ); /* in hitimes_interval.c */
|
362
|
+
|
363
|
+
rb_define_method( cH_Interval, "start_instant", hitimes_interval_start_instant, 0 ); /* in hitimes_interval.c */
|
364
|
+
rb_define_method( cH_Interval, "stop_instant", hitimes_interval_stop_instant, 0 ); /* in hitimes_interval.c */
|
365
|
+
|
366
|
+
rb_define_method( cH_Interval, "start", hitimes_interval_start, 0); /* in hitimes_interval.c */
|
367
|
+
rb_define_method( cH_Interval, "stop", hitimes_interval_stop, 0); /* in hitimes_interval.c */
|
368
|
+
rb_define_method( cH_Interval, "split", hitimes_interval_split, 0); /* in hitimes_interval.c */
|
369
|
+
|
370
|
+
}
|