monotonic.rb 0.6.7 → 0.7.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.
- checksums.yaml +4 -4
- data/CHANGELOG +23 -0
- data/README.md +31 -1
- data/lib/Monotonic/Time.rb +42 -6
- data/lib/Monotonic/Timer.rb +49 -8
- data/lib/Monotonic/VERSION.rb +1 -1
- data/test/Monotonic/Time_test.rb +35 -4
- data/test/Monotonic/Timer_test.rb +49 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 577e4ce149e58981c889c52eaed6256c4c11a5bf2d1e6144513d3cd8c0d72705
|
|
4
|
+
data.tar.gz: 60b83880903cbe10e28ab23462953ecc6b43296c1c39ae08e5c8cc6442697794
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '084908b43a5095d6ff4a3928a6161abb5800ce113714036afdd3bbc89c361886292c603d2f44bd33014d4fa0c5f8e25779c183933e1c4336c2767991ec21b194'
|
|
7
|
+
data.tar.gz: 252ba0130e324f322c37cb4df402a307ff534580ff422fc8b7ddbda494b3e8b28d0c681417dde96989d6d8f1d4dc8f2eb6bd5c9847b167b3176295fc88f27561
|
data/CHANGELOG
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## 20260811
|
|
4
|
+
|
|
5
|
+
0.7.0: Read the clock exactly, and read a clock worth reading exactly.
|
|
6
|
+
|
|
7
|
+
1. ~ lib/Monotonic/Time.rb: Process.clock_gettime is now asked for :nanosecond, where it answers with an Integer, rather than for seconds, where it answers with a Float. A Float's mantissa is of a fixed width wherever it sits, so its absolute resolution falls away as the uptime grows: around 2.2e-16s near 1.0, but only 4.7e-10s at a month of uptime.
|
|
8
|
+
2. + Monotonic::Time#nanoseconds_since_boot: the reading itself, exact.
|
|
9
|
+
3. ~ Monotonic::Time#seconds_since_boot: /attr_reader/derived from the nanosecond reading/, so that the rounding happens where it is asked for rather than where the clock is read. It returns a Float as before.
|
|
10
|
+
4. + Monotonic::NANOSECONDS_PER_SECOND, being needed by both Time and Timer.
|
|
11
|
+
5. + Monotonic::Timer#total_nanoseconds: an elapsed interval as an exact Integer. This is where the reading was formerly spent, an interval being the difference of two Floats drawn from an uptime many orders of magnitude larger than itself.
|
|
12
|
+
6. ~ Monotonic::Timer#total_time: derived from #total_nanoseconds. It returns a Float as before.
|
|
13
|
+
7. ~ Monotonic::Timer#total_time: - the branch upon @finish_time, which moved to a private #finish_nanoseconds, so that the running and stopped cases are distinguished in one place rather than in each caller.
|
|
14
|
+
8. + Monotonic::Timer.clock_name and Monotonic::Time.clock_name, and Monotonic::Timer::CLOCK, being CLOCK_UPTIME_RAW where it is defined and CLOCK_MONOTONIC otherwise. An interval is not an instant and wants a different clock: upon Darwin CLOCK_UPTIME_RAW advances in some 42ns against the 1000ns of CLOCK_MONOTONIC, and holds while the machine sleeps, a closed lid being no part of execution. Linux has no such clock, but its CLOCK_MONOTONIC already holds while suspended and advances finely, so the fallback carries the same meaning and not merely the same name. Exactness alone was worth little upon the old clock, whose 1000ns tick a Float would not have troubled for 142 years of uptime; upon 42ns it begins to tell after six.
|
|
15
|
+
9. ~ Monotonic::Timer: - its use of Monotonic::Time, since the two now read different clocks. @start_time and @finish_time become @start_nanoseconds and @finish_nanoseconds, read through a private #now.
|
|
16
|
+
10. ~ Monotonic::Time::CLOCK, being CLOCK_MONOTONIC still, and now named. #to_time maps an instant back onto the wall clock by way of the boot time, so the clock wanted there is the one tracking time since boot as the wall clock understands it, sleep and all.
|
|
17
|
+
11. + Monotonic::Time.resolution and Monotonic::Timer.resolution, from Process.clock_getres. How finely a clock advances is a property of the processor and the operating system, so it is asked rather than tabulated, and a README sentence about one platform cannot stand in for it. A reading is denominated in nanoseconds whether or not the clock affords them; this is the method which says what a reading is worth.
|
|
18
|
+
12. ~ .clock_name is a method upon both classes rather than a CLOCK_NAME constant, since which clock is read is something found by asking the platform, as .resolution is, and not a property this library declares. A constant would also have frozen a contestable decision: sleep is excluded from a timed interval here, and nothing could have said otherwise. CLOCK stays a constant, being read twice upon every measurement against a floor of some tens of nanoseconds, and is now commented as such.
|
|
19
|
+
13. ~ test/Monotonic/Time_test.rb: ~ the initialize test, which read @seconds_since_boot, to read @nanoseconds_since_boot.
|
|
20
|
+
14. + test/Monotonic/Time_test.rb: tests for .clock_name, .resolution and #nanoseconds_since_boot, and that #seconds_since_boot is that reading expressed in seconds.
|
|
21
|
+
15. + test/Monotonic/Timer_test.rb: tests for #total_nanoseconds, including that it holds while the timer is stopped, and for the clock: which one is chosen, that CLOCK follows .clock_name, that it reports its resolution, and that it is no coarser than the one Monotonic::Time reads.
|
|
22
|
+
16. ~ README.md: + #nanoseconds_since_boot, #total_nanoseconds and .resolution to the description and the usage. The description now distinguishes denomination from resolution, asking for :nanosecond settling only what the figure counts, and points at .resolution rather than making a claim about any one platform.
|
|
23
|
+
17. ~ Monotonic::VERSION: /0.6.7/0.7.0/
|
|
24
|
+
|
|
25
|
+
|
|
3
26
|
## 20260716
|
|
4
27
|
|
|
5
28
|
0.6.7: Block exception bug fix, relicensing, and gem packaging changes.
|
data/README.md
CHANGED
|
@@ -1,24 +1,49 @@
|
|
|
1
1
|
# monotonic.rb
|
|
2
2
|
|
|
3
|
+
|
|
3
4
|
## Description
|
|
4
5
|
|
|
5
6
|
Create accurate timings of excution in Ruby.
|
|
6
7
|
|
|
8
|
+
What accurate means is to capture many digits as an operating system is willing to afford. Hence, the clock is read in nanoseconds by default. If a number in seconds is requested, then that is derived from nanoseconds rather than read directly, so the rounding happens upon request and not before.
|
|
9
|
+
|
|
10
|
+
It tells most upon an elapsed interval, that being the difference of two readings drawn from an uptime many orders of magnitude larger than itself. A `Float` carries a mantissa of fixed width wherever it sits, so its absolute resolution falls away as the uptime grows: around 2.2e-16s near 1.0, but only 4.7e-10s after a month of uptime. Differencing two exact integers spends none of the reading, however long the machine has been up.
|
|
11
|
+
|
|
12
|
+
Which clock is read follows from that. `Monotonic::Timer` measures intervals and so takes the finest available which holds while the machine sleeps, a closed lid being no part of execution: `CLOCK_UPTIME_RAW` upon Darwin, where it advances in some 42ns against the 1000ns of `CLOCK_MONOTONIC`, and `CLOCK_MONOTONIC` elsewhere, which upon Linux already holds while suspended and advances finely. `Monotonic::Time` is an instant rather than an interval, and `#to_time` maps it back onto the wall clock, so it stays upon `CLOCK_MONOTONIC`, sleep and all.
|
|
13
|
+
|
|
14
|
+
How finely a clock advances is the platform's business and not this library's to claim, so it is asked rather than tabulated:
|
|
15
|
+
|
|
16
|
+
```ruby
|
|
17
|
+
Monotonic::Timer.resolution
|
|
18
|
+
# => 42
|
|
19
|
+
Monotonic::Time.resolution
|
|
20
|
+
# => 1000
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
A reading is denominated in nanoseconds whether or not the clock affords them, so that is the method which says what a reading is worth. Two figures give the sense of it upon the finer clock: reading it costs about 34ns against the 42ns it takes to advance, the two being close enough that there is little to be had by going finer, and a pair of `Float`s would not begin to lose it until some six years of uptime — but they would begin.
|
|
24
|
+
|
|
25
|
+
|
|
7
26
|
## Installation
|
|
8
27
|
|
|
9
28
|
Add this line to your application's Gemfile:
|
|
29
|
+
|
|
10
30
|
```ruby
|
|
11
31
|
gem 'monotonic.rb'
|
|
12
32
|
```
|
|
33
|
+
|
|
13
34
|
And then execute:
|
|
35
|
+
|
|
14
36
|
```bash
|
|
15
|
-
$ bundle
|
|
37
|
+
$ bundle install
|
|
16
38
|
```
|
|
39
|
+
|
|
17
40
|
Or install it yourself as:
|
|
41
|
+
|
|
18
42
|
```bash
|
|
19
43
|
$ gem install monotonic.rb
|
|
20
44
|
```
|
|
21
45
|
|
|
46
|
+
|
|
22
47
|
## Usage
|
|
23
48
|
|
|
24
49
|
### Monotonic::Time
|
|
@@ -26,6 +51,8 @@ Or install it yourself as:
|
|
|
26
51
|
```ruby
|
|
27
52
|
require 'monotonic.rb'
|
|
28
53
|
monotonic_time = Monotonic::Time.new
|
|
54
|
+
monotonic_time.nanoseconds_since_boot
|
|
55
|
+
# => 2614365376498000
|
|
29
56
|
monotonic_time.seconds_since_boot
|
|
30
57
|
# => 1208799.325906
|
|
31
58
|
monotonic_time + Monotonic::Time.now
|
|
@@ -47,6 +74,8 @@ Or install it yourself as:
|
|
|
47
74
|
i = 0
|
|
48
75
|
1_000_000.times{puts i += 1}
|
|
49
76
|
timer.stop
|
|
77
|
+
timer.total_nanoseconds
|
|
78
|
+
# => 27734000
|
|
50
79
|
timer.total_time
|
|
51
80
|
# => 7.166559999808669
|
|
52
81
|
```
|
|
@@ -90,6 +119,7 @@ Or install it yourself as:
|
|
|
90
119
|
# => 7.033131000120193
|
|
91
120
|
```
|
|
92
121
|
|
|
122
|
+
|
|
93
123
|
## Contributing
|
|
94
124
|
|
|
95
125
|
1. Fork it ( https://github.com/thoran/monotonic.rb/fork )
|
data/lib/Monotonic/Time.rb
CHANGED
|
@@ -4,34 +4,70 @@
|
|
|
4
4
|
require 'sys-uptime'
|
|
5
5
|
|
|
6
6
|
module Monotonic
|
|
7
|
+
NANOSECONDS_PER_SECOND = 1_000_000_000
|
|
8
|
+
|
|
7
9
|
class Time
|
|
8
10
|
class << self
|
|
11
|
+
# An instant, which #to_time maps back onto the wall clock by way of the
|
|
12
|
+
# boot time, so the clock wanted here is the one which tracks time since
|
|
13
|
+
# boot as the wall clock understands it. That is CLOCK_MONOTONIC, sleep
|
|
14
|
+
# and all. Monotonic::Timer measures intervals rather than instants and
|
|
15
|
+
# chooses a finer clock of its own.
|
|
16
|
+
#
|
|
17
|
+
# Unlike Timer's, this one is chosen rather than found, there being no
|
|
18
|
+
# alternative which would still answer to #to_time. It is a method all
|
|
19
|
+
# the same, so that the two classes answer the question alike.
|
|
20
|
+
def clock_name
|
|
21
|
+
:CLOCK_MONOTONIC
|
|
22
|
+
end
|
|
23
|
+
|
|
9
24
|
def now
|
|
10
25
|
self.new
|
|
11
26
|
end
|
|
27
|
+
|
|
28
|
+
# How finely this clock advances, in nanoseconds. It is asked rather than
|
|
29
|
+
# tabulated, being a property of the processor and the operating system
|
|
30
|
+
# and not of this library: upon macOS CLOCK_MONOTONIC answers 1000 here.
|
|
31
|
+
# A reading is denominated in nanoseconds whatever the answer, so this is
|
|
32
|
+
# the method which says what a reading is worth.
|
|
33
|
+
def resolution
|
|
34
|
+
Process.clock_getres(CLOCK, :nanosecond)
|
|
35
|
+
end
|
|
12
36
|
end # class << self
|
|
13
37
|
|
|
14
|
-
|
|
38
|
+
# Read upon every instance, so a constant rather than a lookup. It follows
|
|
39
|
+
# .clock_name, and so must come after it.
|
|
40
|
+
CLOCK = Process.const_get(clock_name)
|
|
41
|
+
|
|
42
|
+
attr_reader :nanoseconds_since_boot
|
|
43
|
+
|
|
44
|
+
# The clock is read in nanoseconds because it answers there with an Integer,
|
|
45
|
+
# which is exact and stays exact however long the machine has been up.
|
|
46
|
+
# Seconds are derived rather than read, so that the reading loses nothing and
|
|
47
|
+
# the rounding happens where it is asked for.
|
|
48
|
+
def seconds_since_boot
|
|
49
|
+
@nanoseconds_since_boot / NANOSECONDS_PER_SECOND.to_f
|
|
50
|
+
end
|
|
15
51
|
|
|
16
52
|
def initialize
|
|
17
53
|
@boot_time = Sys::Uptime.boot_time
|
|
18
|
-
@
|
|
54
|
+
@nanoseconds_since_boot = Process.clock_gettime(CLOCK, :nanosecond)
|
|
19
55
|
end
|
|
20
56
|
|
|
21
57
|
def +(monotonic_time_addend)
|
|
22
|
-
|
|
58
|
+
seconds_since_boot + monotonic_time_addend.seconds_since_boot
|
|
23
59
|
end
|
|
24
60
|
|
|
25
61
|
def -(monotonic_time_subtrahend)
|
|
26
|
-
|
|
62
|
+
seconds_since_boot - monotonic_time_subtrahend.seconds_since_boot
|
|
27
63
|
end
|
|
28
64
|
|
|
29
65
|
def to_s
|
|
30
|
-
"#{
|
|
66
|
+
"#{seconds_since_boot} seconds since boot."
|
|
31
67
|
end
|
|
32
68
|
|
|
33
69
|
def to_time
|
|
34
|
-
@boot_time +
|
|
70
|
+
@boot_time + seconds_since_boot
|
|
35
71
|
end
|
|
36
72
|
end
|
|
37
73
|
end
|
data/lib/Monotonic/Timer.rb
CHANGED
|
@@ -6,27 +6,57 @@ require_relative './Time'
|
|
|
6
6
|
module Monotonic
|
|
7
7
|
class Timer
|
|
8
8
|
class << self
|
|
9
|
+
# An interval is not an instant, and wants a different clock. Upon Darwin
|
|
10
|
+
# CLOCK_UPTIME_RAW advances in some 42ns against the 1000ns of
|
|
11
|
+
# CLOCK_MONOTONIC, and holds while the machine sleeps, which is the right
|
|
12
|
+
# answer for a timed block: a closed lid is not execution. Linux has no
|
|
13
|
+
# such clock, but its CLOCK_MONOTONIC already holds while suspended and
|
|
14
|
+
# advances finely, so the fallback carries the same meaning and not merely
|
|
15
|
+
# the same name.
|
|
16
|
+
#
|
|
17
|
+
# Which clocks exist is the platform's business, so this is asked rather
|
|
18
|
+
# than declared, as .resolution is.
|
|
19
|
+
def clock_name
|
|
20
|
+
@clock_name ||= %i[CLOCK_UPTIME_RAW CLOCK_MONOTONIC].find{|name| Process.const_defined?(name)}
|
|
21
|
+
end
|
|
22
|
+
|
|
9
23
|
def time(&block)
|
|
10
24
|
timer = Timer.new
|
|
11
25
|
timer.time(&block)
|
|
12
26
|
end
|
|
27
|
+
|
|
28
|
+
# How finely this clock advances, in nanoseconds. Asked of the platform
|
|
29
|
+
# rather than claimed by the library, and worth asking: a reading is
|
|
30
|
+
# denominated in nanoseconds whether the clock affords them or not.
|
|
31
|
+
def resolution
|
|
32
|
+
Process.clock_getres(CLOCK, :nanosecond)
|
|
33
|
+
end
|
|
13
34
|
end # class << self
|
|
14
35
|
|
|
36
|
+
# Read twice upon every measurement, against a floor of some tens of
|
|
37
|
+
# nanoseconds, so this is the one place here where a constant is worth the
|
|
38
|
+
# rigidity: a method call would be a measurable part of what it measures.
|
|
39
|
+
# It follows .clock_name, and so must come after it.
|
|
40
|
+
CLOCK = Process.const_get(clock_name)
|
|
41
|
+
|
|
15
42
|
def start
|
|
16
|
-
@
|
|
17
|
-
@
|
|
43
|
+
@finish_nanoseconds = nil
|
|
44
|
+
@start_nanoseconds = now
|
|
18
45
|
end
|
|
19
46
|
|
|
20
47
|
def stop
|
|
21
|
-
@
|
|
48
|
+
@finish_nanoseconds = now
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Two exact integers differenced, which spends none of the reading. A pair
|
|
52
|
+
# of Floats would not begin to lose the clock at this resolution until some
|
|
53
|
+
# six years of uptime, but they would begin.
|
|
54
|
+
def total_nanoseconds
|
|
55
|
+
finish_nanoseconds - @start_nanoseconds
|
|
22
56
|
end
|
|
23
57
|
|
|
24
58
|
def total_time
|
|
25
|
-
|
|
26
|
-
@finish_time - @start_time
|
|
27
|
-
else
|
|
28
|
-
Monotonic::Time.now - @start_time
|
|
29
|
-
end
|
|
59
|
+
total_nanoseconds / NANOSECONDS_PER_SECOND.to_f
|
|
30
60
|
end
|
|
31
61
|
|
|
32
62
|
def time
|
|
@@ -38,5 +68,16 @@ module Monotonic
|
|
|
38
68
|
end
|
|
39
69
|
total_time
|
|
40
70
|
end
|
|
71
|
+
|
|
72
|
+
private
|
|
73
|
+
|
|
74
|
+
# A timer which has not been stopped is still running, so the finish is now.
|
|
75
|
+
def finish_nanoseconds
|
|
76
|
+
@finish_nanoseconds || now
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def now
|
|
80
|
+
Process.clock_gettime(CLOCK, :nanosecond)
|
|
81
|
+
end
|
|
41
82
|
end
|
|
42
83
|
end
|
data/lib/Monotonic/VERSION.rb
CHANGED
data/test/Monotonic/Time_test.rb
CHANGED
|
@@ -12,16 +12,47 @@ describe Monotonic::Time do
|
|
|
12
12
|
.must_equal(Sys::Uptime.boot_time)
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
it "the
|
|
16
|
-
expect(subject.instance_variable_get(:@
|
|
17
|
-
.must_equal(Process.clock_gettime(Process::CLOCK_MONOTONIC).round(2))
|
|
15
|
+
it "the reading is taken from the monotonic clock in nanoseconds" do
|
|
16
|
+
expect((subject.instance_variable_get(:@nanoseconds_since_boot) / 1_000_000_000.0).round(2)) \
|
|
17
|
+
.must_equal((Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond) / 1_000_000_000.0).round(2))
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
describe ".clock_name" do
|
|
22
|
+
it "is the clock which tracks time since boot as the wall clock understands it" do
|
|
23
|
+
expect(Monotonic::Time.clock_name).must_equal(:CLOCK_MONOTONIC)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "names the clock which is read" do
|
|
27
|
+
expect(Monotonic::Time::CLOCK).must_equal(Process.const_get(Monotonic::Time.clock_name))
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
describe ".resolution" do
|
|
32
|
+
it "returns how finely the clock advances, in nanoseconds" do
|
|
33
|
+
expect(Monotonic::Time.resolution) \
|
|
34
|
+
.must_equal(Process.clock_getres(Process::CLOCK_MONOTONIC, :nanosecond))
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "returns an instance of integer" do
|
|
38
|
+
expect(Monotonic::Time.resolution.class).must_equal(Integer)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
describe "#nanoseconds_since_boot" do
|
|
43
|
+
it "returns an instance of integer" do
|
|
44
|
+
expect((subject.nanoseconds_since_boot).class).must_equal(Integer)
|
|
18
45
|
end
|
|
19
46
|
end
|
|
20
47
|
|
|
21
48
|
describe "#seconds_since_boot" do
|
|
22
|
-
it "returns an instance of
|
|
49
|
+
it "returns an instance of float" do
|
|
23
50
|
expect((subject.seconds_since_boot).class).must_equal(Float)
|
|
24
51
|
end
|
|
52
|
+
|
|
53
|
+
it "is the nanoseconds reading expressed in seconds" do
|
|
54
|
+
expect(subject.seconds_since_boot).must_equal(subject.nanoseconds_since_boot / 1_000_000_000.0)
|
|
55
|
+
end
|
|
25
56
|
end
|
|
26
57
|
|
|
27
58
|
describe "#+" do
|
|
@@ -107,4 +107,53 @@ describe Monotonic::Timer do
|
|
|
107
107
|
expect(timer.total_time.round).must_equal(1)
|
|
108
108
|
end
|
|
109
109
|
end
|
|
110
|
+
|
|
111
|
+
context "the clock" do
|
|
112
|
+
it "is the finest available which holds while the machine sleeps" do
|
|
113
|
+
expect(Monotonic::Timer.clock_name) \
|
|
114
|
+
.must_equal(Process.const_defined?(:CLOCK_UPTIME_RAW) ? :CLOCK_UPTIME_RAW : :CLOCK_MONOTONIC)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
it "is asked of the platform rather than declared" do
|
|
118
|
+
expect(Monotonic::Timer::CLOCK).must_equal(Process.const_get(Monotonic::Timer.clock_name))
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
it "reports its resolution rather than leaving it to be assumed" do
|
|
122
|
+
expect(Monotonic::Timer.resolution) \
|
|
123
|
+
.must_equal(Process.clock_getres(Monotonic::Timer::CLOCK, :nanosecond))
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
it "is no coarser than the one Monotonic::Time reads" do
|
|
127
|
+
expect(Monotonic::Timer.resolution).must_be :<=, Monotonic::Time.resolution
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
context "in nanoseconds" do
|
|
132
|
+
it "returns an instance of integer" do
|
|
133
|
+
timer = Monotonic::Timer.new
|
|
134
|
+
timer.start
|
|
135
|
+
sleep 1
|
|
136
|
+
timer.stop
|
|
137
|
+
expect(timer.total_nanoseconds.class).must_equal(Integer)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
it "is the total time expressed in nanoseconds" do
|
|
141
|
+
timer = Monotonic::Timer.new
|
|
142
|
+
timer.start
|
|
143
|
+
sleep 1
|
|
144
|
+
timer.stop
|
|
145
|
+
expect(timer.total_nanoseconds / 1_000_000_000.0).must_equal(timer.total_time)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
it "holds while the timer is stopped and runs on while it is not" do
|
|
149
|
+
timer = Monotonic::Timer.new
|
|
150
|
+
timer.start
|
|
151
|
+
timer.stop
|
|
152
|
+
held = timer.total_nanoseconds
|
|
153
|
+
sleep 1
|
|
154
|
+
expect(timer.total_nanoseconds).must_equal(held)
|
|
155
|
+
timer.start
|
|
156
|
+
expect(timer.total_nanoseconds).must_be :>, 0
|
|
157
|
+
end
|
|
158
|
+
end
|
|
110
159
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: monotonic.rb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- thoran
|
|
@@ -100,7 +100,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
100
100
|
- !ruby/object:Gem::Version
|
|
101
101
|
version: '0'
|
|
102
102
|
requirements: []
|
|
103
|
-
rubygems_version: 4.0.
|
|
103
|
+
rubygems_version: 4.0.18
|
|
104
104
|
specification_version: 4
|
|
105
105
|
summary: Monotonic timing made easy.
|
|
106
106
|
test_files: []
|