absolute_time 0.1.0
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.
- data/.gitignore +10 -0
- data/Gemfile +4 -0
- data/README +44 -0
- data/Rakefile +1 -0
- data/absolute_time.c +135 -0
- data/absolute_time.gemspec +29 -0
- data/extconf.rb +31 -0
- metadata +79 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
AbsoluteTime
|
4
|
+
|
5
|
+
This gem provides a monotonically increasing timer to permit safe measurement of time intervals.
|
6
|
+
|
7
|
+
Using Time.now() for measuring intervals is not reliable—and sometimes unsafe—because the
|
8
|
+
system clock may be stepped forwards or backwards between the two measurements, or may be
|
9
|
+
running slower or faster than real time in order to effect clock synchronization with UTC.
|
10
|
+
|
11
|
+
The module uses OS-specific functions such as mach_absolute_time() and clock_gettime() to
|
12
|
+
access the system tick counter. The time values returned by this module cannot be interpreted
|
13
|
+
as real time clock values; they are only useful for comparison with another time value from
|
14
|
+
this module.
|
15
|
+
|
16
|
+
Also, please note that because the timer is dependent on the time since the system was
|
17
|
+
booted, it is not meaningful to compare values of AbsoluteTime.now across reboots or between
|
18
|
+
different machines. It should, however, be safe to compare a timer value recorded by one process
|
19
|
+
with a value recorded by a different process on the same machine.
|
20
|
+
|
21
|
+
The resolution of the timer is system-dependent.
|
22
|
+
|
23
|
+
|
24
|
+
Usage:
|
25
|
+
|
26
|
+
# Is a monotonically increasing timer available on this system?
|
27
|
+
>> AbsoluteTime.monotonic?
|
28
|
+
=> true
|
29
|
+
|
30
|
+
# Time an action by recording the start and end times.
|
31
|
+
>> start_time = AbsoluteTime.now
|
32
|
+
>> value = function_that_takes_a_long_time()
|
33
|
+
>> end_time = AbsoluteTime.now
|
34
|
+
>> puts "Function took #{end_time - start_time} seconds to complete."
|
35
|
+
|
36
|
+
Function took 5.0002783499658108 seconds to complete.
|
37
|
+
|
38
|
+
# Time an action using AbsoluteTime.measure, which acts like Benchmark.measure.
|
39
|
+
>> AbsoluteTime.measure { function_that_takes_a_long_time() }
|
40
|
+
=> 5.0002783499658108
|
41
|
+
|
42
|
+
Supported platforms: Darwin (Mac OS X), FreeBSD, Linux
|
43
|
+
|
44
|
+
If you can add support for another platform, please do so and send me a pull request on GitHub. A Windows implementation using GetTickCount64() / GetTickCount() / QueryPerformanceCounter() would be much appreciated!
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/absolute_time.c
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
/*
|
2
|
+
Copyright (C) 2011 Brian Buchanan. All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions
|
6
|
+
are met:
|
7
|
+
1. Redistributions of source code must retain the above copyright
|
8
|
+
notice, this list of conditions and the following disclaimer.
|
9
|
+
2. Redistributions in binary form must reproduce the above copyright
|
10
|
+
notice, this list of conditions and the following disclaimer in the
|
11
|
+
documentation and/or other materials provided with the distribution.
|
12
|
+
|
13
|
+
THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
14
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
15
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
16
|
+
ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
17
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
18
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
19
|
+
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
20
|
+
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
21
|
+
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
22
|
+
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
23
|
+
SUCH DAMAGE.
|
24
|
+
*/
|
25
|
+
|
26
|
+
#include <ruby.h>
|
27
|
+
#include <time.h>
|
28
|
+
#ifdef HAVE_MACH_H
|
29
|
+
#include <mach/mach.h>
|
30
|
+
#endif
|
31
|
+
#ifdef HAVE_MACH_MACH_TIME_H
|
32
|
+
#include <mach/mach_time.h>
|
33
|
+
#endif
|
34
|
+
|
35
|
+
static double get_absolute_time(void);
|
36
|
+
|
37
|
+
/*
|
38
|
+
* Document-module: AbsoluteTime
|
39
|
+
*
|
40
|
+
* Ruby interface to monotonically-increasing system timer.
|
41
|
+
*/
|
42
|
+
|
43
|
+
/*
|
44
|
+
* call-seq:
|
45
|
+
* AbsoluteTime.now() -> time
|
46
|
+
*
|
47
|
+
* Returns the current value of the system timer as a floating-point number of seconds.
|
48
|
+
* Although the units of the return value are seconds, they cannot be safely
|
49
|
+
* interpreted as a wall clock time. The return value is only useful when compared to
|
50
|
+
* the return value of a previous or subsequent call to AbsoluteTime.now().
|
51
|
+
*
|
52
|
+
* If a monotonically increasing system clock is not available, this function falls back
|
53
|
+
* to using the wall clock time. You can check to see whether a monotonic clock is
|
54
|
+
* available using AbsoluteTime.monotonic?()
|
55
|
+
*/
|
56
|
+
static VALUE
|
57
|
+
module_now(VALUE self_)
|
58
|
+
{
|
59
|
+
return rb_float_new(get_absolute_time());
|
60
|
+
}
|
61
|
+
|
62
|
+
/*
|
63
|
+
* call-seq:
|
64
|
+
* AbsoluteTime.realtime() { || ... } -> seconds
|
65
|
+
*
|
66
|
+
* Like Benchmark.realtime(), returns the elapsed time to execute the specified block,
|
67
|
+
* as a floating-point number of seconds.
|
68
|
+
*/
|
69
|
+
static VALUE
|
70
|
+
module_realtime(VALUE self_)
|
71
|
+
{
|
72
|
+
double start_time, end_time;
|
73
|
+
|
74
|
+
start_time = get_absolute_time();
|
75
|
+
rb_yield(Qnil);
|
76
|
+
end_time = get_absolute_time();
|
77
|
+
|
78
|
+
return rb_float_new(end_time - start_time);
|
79
|
+
}
|
80
|
+
|
81
|
+
/*
|
82
|
+
* call-seq:
|
83
|
+
* AbsoluteTime.monotonic?() -> true | false
|
84
|
+
*
|
85
|
+
* Returns true if this module is able to use a guaranteed monotonically-increasing clock,
|
86
|
+
* false otherwise.
|
87
|
+
*/
|
88
|
+
static VALUE
|
89
|
+
module_is_monotonic(VALUE self_)
|
90
|
+
{
|
91
|
+
#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) || defined(HAVE_MACH_MACH_TIME_H)
|
92
|
+
return Qtrue;
|
93
|
+
#else
|
94
|
+
return Qfalse;
|
95
|
+
#endif
|
96
|
+
}
|
97
|
+
|
98
|
+
void
|
99
|
+
Init_absolute_time(void)
|
100
|
+
{
|
101
|
+
VALUE absolute_time_module = rb_define_module ("AbsoluteTime");
|
102
|
+
rb_define_singleton_method (absolute_time_module, "now", module_now, 0);
|
103
|
+
rb_define_singleton_method (absolute_time_module, "realtime", module_realtime, 0);
|
104
|
+
rb_define_singleton_method (absolute_time_module, "monotonic?", module_is_monotonic, 0);
|
105
|
+
}
|
106
|
+
|
107
|
+
static double
|
108
|
+
get_absolute_time(void)
|
109
|
+
{
|
110
|
+
#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
|
111
|
+
struct timespec ts;
|
112
|
+
|
113
|
+
if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) {
|
114
|
+
rb_sys_fail("clock_gettime");
|
115
|
+
}
|
116
|
+
return (double)ts.tv_sec + (double)ts.tv_nsec / 1e9;
|
117
|
+
#else
|
118
|
+
# if defined(HAVE_MACH_MACH_TIME_H)
|
119
|
+
uint64_t t;
|
120
|
+
static mach_timebase_info_data_t timebase_info;
|
121
|
+
|
122
|
+
/* If this is the first time we've run the function, then get the timebase info. */
|
123
|
+
if (timebase_info.denom == 0)
|
124
|
+
mach_timebase_info(&timebase_info);
|
125
|
+
|
126
|
+
t = mach_absolute_time();
|
127
|
+
return (double)t * timebase_info.numer / timebase_info.denom / 1e9;
|
128
|
+
# else
|
129
|
+
struct timeval tv;
|
130
|
+
if (gettimeofday(&tv, 0) < 0)
|
131
|
+
rb_sys_fail("gettimeofday");
|
132
|
+
return (double)tv.tv_sec + (double)tv.tv_usec / 1e6;
|
133
|
+
# endif
|
134
|
+
#endif
|
135
|
+
}
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
Gem::Specification.new do |s|
|
3
|
+
s.name = "absolute_time"
|
4
|
+
s.version = '0.1.0'
|
5
|
+
s.authors = ["Brian Buchanan"]
|
6
|
+
s.email = ["brian@tiogalake.com"]
|
7
|
+
s.homepage = ""
|
8
|
+
s.summary = %q{Reliable monotonically increasing timer for measuring time intervals}
|
9
|
+
s.description = %q{This gem provides a monotonically increasing timer to permit safe measurement of time intervals.
|
10
|
+
|
11
|
+
Using Time.now for measuring intervals is not reliable (and sometimes unsafe) because the
|
12
|
+
system clock may be stepped forwards or backwards between the two measurements, or may be
|
13
|
+
running slower or faster than real time in order to effect clock synchronization with UTC.
|
14
|
+
|
15
|
+
The module uses OS-specific functions such as mach_absolute_time() and clock_gettime() to
|
16
|
+
access the system tick counter. The time values returned by this module cannot be interpreted
|
17
|
+
as real time clock values; they are only useful for comparison with another time value from
|
18
|
+
this module.
|
19
|
+
}
|
20
|
+
|
21
|
+
s.rubyforge_project = "absolute_time"
|
22
|
+
|
23
|
+
s.files = `git ls-files`.split("\n")
|
24
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
25
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
26
|
+
s.extensions = 'extconf.rb'
|
27
|
+
s.has_rdoc = true
|
28
|
+
s.extra_rdoc_files = `git ls-files -- *.c`.split("\n")
|
29
|
+
end
|
data/extconf.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# Copyright (C) 2011 Brian Buchanan. All rights reserved.
|
2
|
+
#
|
3
|
+
# Redistribution and use in source and binary forms, with or without
|
4
|
+
# modification, are permitted provided that the following conditions
|
5
|
+
# are met:
|
6
|
+
# 1. Redistributions of source code must retain the above copyright
|
7
|
+
# notice, this list of conditions and the following disclaimer.
|
8
|
+
# 2. Redistributions in binary form must reproduce the above copyright
|
9
|
+
# notice, this list of conditions and the following disclaimer in the
|
10
|
+
# documentation and/or other materials provided with the distribution.
|
11
|
+
#
|
12
|
+
# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
13
|
+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
14
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
15
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
16
|
+
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
17
|
+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
18
|
+
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
19
|
+
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
20
|
+
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
21
|
+
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
22
|
+
# SUCH DAMAGE.
|
23
|
+
|
24
|
+
require 'mkmf'
|
25
|
+
dir_config('absolute_time')
|
26
|
+
|
27
|
+
have_header('mach/mach.h')
|
28
|
+
have_header('mach/mach_time.h')
|
29
|
+
have_func('clock_gettime')
|
30
|
+
|
31
|
+
create_makefile('absolute_time')
|
metadata
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: absolute_time
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Brian Buchanan
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-09-17 00:00:00.000000000Z
|
13
|
+
dependencies: []
|
14
|
+
description: ! 'This gem provides a monotonically increasing timer to permit safe
|
15
|
+
measurement of time intervals.
|
16
|
+
|
17
|
+
|
18
|
+
Using Time.now for measuring intervals is not reliable (and sometimes unsafe) because
|
19
|
+
the
|
20
|
+
|
21
|
+
system clock may be stepped forwards or backwards between the two measurements,
|
22
|
+
or may be
|
23
|
+
|
24
|
+
running slower or faster than real time in order to effect clock synchronization
|
25
|
+
with UTC.
|
26
|
+
|
27
|
+
|
28
|
+
The module uses OS-specific functions such as mach_absolute_time() and clock_gettime()
|
29
|
+
to
|
30
|
+
|
31
|
+
access the system tick counter. The time values returned by this module cannot
|
32
|
+
be interpreted
|
33
|
+
|
34
|
+
as real time clock values; they are only useful for comparison with another time
|
35
|
+
value from
|
36
|
+
|
37
|
+
this module.
|
38
|
+
|
39
|
+
'
|
40
|
+
email:
|
41
|
+
- brian@tiogalake.com
|
42
|
+
executables: []
|
43
|
+
extensions:
|
44
|
+
- extconf.rb
|
45
|
+
extra_rdoc_files:
|
46
|
+
- absolute_time.c
|
47
|
+
files:
|
48
|
+
- .gitignore
|
49
|
+
- Gemfile
|
50
|
+
- README
|
51
|
+
- Rakefile
|
52
|
+
- absolute_time.c
|
53
|
+
- absolute_time.gemspec
|
54
|
+
- extconf.rb
|
55
|
+
homepage: ''
|
56
|
+
licenses: []
|
57
|
+
post_install_message:
|
58
|
+
rdoc_options: []
|
59
|
+
require_paths:
|
60
|
+
- lib
|
61
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ! '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
none: false
|
69
|
+
requirements:
|
70
|
+
- - ! '>='
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
requirements: []
|
74
|
+
rubyforge_project: absolute_time
|
75
|
+
rubygems_version: 1.8.5
|
76
|
+
signing_key:
|
77
|
+
specification_version: 3
|
78
|
+
summary: Reliable monotonically increasing timer for measuring time intervals
|
79
|
+
test_files: []
|