absolute_time 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|