hitimes 1.3.1 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CONTRIBUTING.md +1 -12
- data/HISTORY.md +26 -2
- data/Manifest.txt +5 -31
- data/README.md +44 -59
- data/hitimes.gemspec +26 -0
- data/lib/hitimes/initialize.rb +104 -0
- data/lib/hitimes/instant.rb +41 -0
- data/lib/hitimes/interval.rb +171 -0
- data/lib/hitimes/metric.rb +18 -22
- data/lib/hitimes/mutexed_stats.rb +3 -20
- data/lib/hitimes/paths.rb +16 -14
- data/lib/hitimes/stats.rb +119 -22
- data/lib/hitimes/timed_metric.rb +43 -42
- data/lib/hitimes/timed_value_metric.rb +43 -43
- data/lib/hitimes/value_metric.rb +16 -15
- data/lib/hitimes/version.rb +3 -1
- data/lib/hitimes.rb +14 -41
- metadata +24 -157
- data/Rakefile +0 -28
- data/examples/benchmarks.rb +0 -113
- data/examples/stats.rb +0 -31
- data/ext/hitimes/c/extconf.rb +0 -24
- data/ext/hitimes/c/hitimes.c +0 -37
- data/ext/hitimes/c/hitimes_instant_clock_gettime.c +0 -28
- data/ext/hitimes/c/hitimes_instant_osx.c +0 -48
- data/ext/hitimes/c/hitimes_instant_windows.c +0 -27
- data/ext/hitimes/c/hitimes_interval.c +0 -370
- data/ext/hitimes/c/hitimes_interval.h +0 -73
- data/ext/hitimes/c/hitimes_stats.c +0 -269
- data/ext/hitimes/c/hitimes_stats.h +0 -30
- data/ext/hitimes/java/src/hitimes/Hitimes.java +0 -63
- data/ext/hitimes/java/src/hitimes/HitimesInterval.java +0 -176
- data/ext/hitimes/java/src/hitimes/HitimesService.java +0 -16
- data/ext/hitimes/java/src/hitimes/HitimesStats.java +0 -112
- data/spec/hitimes_spec.rb +0 -24
- data/spec/interval_spec.rb +0 -136
- data/spec/metric_spec.rb +0 -28
- data/spec/mutex_stats_spec.rb +0 -36
- data/spec/paths_spec.rb +0 -11
- data/spec/spec_helper.rb +0 -11
- data/spec/stats_spec.rb +0 -98
- data/spec/timed_metric_spec.rb +0 -155
- data/spec/timed_value_metric_spec.rb +0 -171
- data/spec/value_metric_spec.rb +0 -108
- data/spec/version_spec.rb +0 -7
- data/tasks/default.rake +0 -242
- data/tasks/extension.rake +0 -38
- data/tasks/this.rb +0 -208
- /data/{LICENSE → LICENSE.txt} +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d79a16734531380e103efb7bf1af93e5c4e465185f5a47f1c0ab6d2dcc8bb5e7
|
4
|
+
data.tar.gz: deb8a23bdc8e0f35b6dccbd6fd4535ffdfa4c5bdd11ff44fa488a53baa090245
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 358edcfe776e98c69100f01065d5f9ac12452353736180f8bf1d04e240cddc1bafcc43078b949c26ef40709acce3f2ac28bb65fed28a7e45301dd2a9c607a4ac
|
7
|
+
data.tar.gz: 3c6296fd094227654048f8bda301435442d6c0169b12322253ba07b1486a4137549ff4f3f11e7f5f09cd3c12f4a78eb92ba9055ebd99d5b6a4eab452ac4f16db
|
data/CONTRIBUTING.md
CHANGED
@@ -27,23 +27,12 @@ easiest way to contribute.
|
|
27
27
|
* Fork the [repo][].
|
28
28
|
* Create a new branch for your issue: `git checkout -b issue/my-issue`
|
29
29
|
* Lovingly craft your contribution:
|
30
|
-
* `
|
30
|
+
* `bin/setup` to get started
|
31
31
|
* `rake test` to run tests
|
32
32
|
* Make sure that `rake test` passes. Its important, I said it twice.
|
33
33
|
* Add yourself to the contributors section below.
|
34
34
|
* Submit your [pull request][].
|
35
35
|
|
36
|
-
## Building Windows Binaries
|
37
|
-
|
38
|
-
This is done using https://github.com/rake-compiler/rake-compiler-dock
|
39
|
-
|
40
|
-
1. have VirtualBox installed
|
41
|
-
2. have Docker Machine installed (https://docs.docker.com/engine/installation/)
|
42
|
-
3. `gem install rake-compiler-dock`
|
43
|
-
4. `rake-compiler-dock` (this could take a while)
|
44
|
-
5. `bundle`
|
45
|
-
6. `rake cross native gem`
|
46
|
-
|
47
36
|
# Contributors
|
48
37
|
|
49
38
|
* Jeremy Hinegardner
|
data/HISTORY.md
CHANGED
@@ -1,4 +1,28 @@
|
|
1
1
|
# Hitimes Changelog
|
2
|
+
## Version 3.0.0 - 2024-05-01
|
3
|
+
|
4
|
+
* Migrated to SemaphoreCI for doing full test runs on all active ruby versions.
|
5
|
+
* Remove the dependency on `Process.clock_getres` as it is unreliable.
|
6
|
+
* This has the effect of deprecating some Hitimes constants that had been documented as public. These are now removed as this is a major version update
|
7
|
+
- `Hitimes::CLOCK_RESOLUTION_NANOSECONDS`
|
8
|
+
- `Hitimes::CLOCK_RESOLUTION_SECONDS`
|
9
|
+
- `Hitimes::INSTANT_CONVERSION_FACTOR`
|
10
|
+
- `Hitimes.clock_resolution_description`
|
11
|
+
- `Hitimes.clock_description`
|
12
|
+
* Added Rubocop for some coding consistency
|
13
|
+
* Updated the supported ruby version to be 3.0 and up
|
14
|
+
* Updated all dependencies
|
15
|
+
* Changed how all the `assert_delta` style tests were done so they were not so flakey
|
16
|
+
* Hitimes will now emit a `warn` message if it ends up using `CLOCK_REALTIME`
|
17
|
+
* Hitimes will raise an exception if it cannot find a valid clock id. This is a bug and a message to file a report is in the exception
|
18
|
+
|
19
|
+
## Version 2.0.0 2019-09-23
|
20
|
+
|
21
|
+
* Remove the C and Java extensions as `Process.clock_gettime()` has the same
|
22
|
+
resolution as what the extensions did.
|
23
|
+
* Update all depedencies and resolve deprecations
|
24
|
+
* Now usable on truffleruby
|
25
|
+
|
2
26
|
## Version 1.3.1 2019-01-18
|
3
27
|
|
4
28
|
* Update jruby extension to not use global runtime state (thanks @kares) (#70)
|
@@ -76,7 +100,7 @@
|
|
76
100
|
|
77
101
|
## Version 1.0.3 2009-06-28
|
78
102
|
|
79
|
-
* Fix bug with time.h on linode (reported by Roger Pack)
|
103
|
+
* Fix bug with time.h on linode (reported by Roger Pack)
|
80
104
|
* Fix potential garbage collection issue with Interval class
|
81
105
|
* Windows gem is now a fat binary to support installing in 1.8 or 1.9 from the
|
82
106
|
same gem
|
@@ -105,7 +129,7 @@
|
|
105
129
|
|
106
130
|
* Added new stat 'rate'
|
107
131
|
* Added new stat method to_hash
|
108
|
-
* Added Hitimes::MutexedStats class for threadsafe stats collection
|
132
|
+
* Added Hitimes::MutexedStats class for threadsafe stats collection
|
109
133
|
- not needed when used in MRI 1.8.x
|
110
134
|
* remove stale dependency on mkrf
|
111
135
|
|
data/Manifest.txt
CHANGED
@@ -1,25 +1,13 @@
|
|
1
1
|
CONTRIBUTING.md
|
2
2
|
HISTORY.md
|
3
|
-
LICENSE
|
3
|
+
LICENSE.txt
|
4
4
|
Manifest.txt
|
5
5
|
README.md
|
6
|
-
|
7
|
-
examples/benchmarks.rb
|
8
|
-
examples/stats.rb
|
9
|
-
ext/hitimes/c/extconf.rb
|
10
|
-
ext/hitimes/c/hitimes.c
|
11
|
-
ext/hitimes/c/hitimes_instant_clock_gettime.c
|
12
|
-
ext/hitimes/c/hitimes_instant_osx.c
|
13
|
-
ext/hitimes/c/hitimes_instant_windows.c
|
14
|
-
ext/hitimes/c/hitimes_interval.c
|
15
|
-
ext/hitimes/c/hitimes_interval.h
|
16
|
-
ext/hitimes/c/hitimes_stats.c
|
17
|
-
ext/hitimes/c/hitimes_stats.h
|
18
|
-
ext/hitimes/java/src/hitimes/Hitimes.java
|
19
|
-
ext/hitimes/java/src/hitimes/HitimesInterval.java
|
20
|
-
ext/hitimes/java/src/hitimes/HitimesService.java
|
21
|
-
ext/hitimes/java/src/hitimes/HitimesStats.java
|
6
|
+
hitimes.gemspec
|
22
7
|
lib/hitimes.rb
|
8
|
+
lib/hitimes/initialize.rb
|
9
|
+
lib/hitimes/instant.rb
|
10
|
+
lib/hitimes/interval.rb
|
23
11
|
lib/hitimes/metric.rb
|
24
12
|
lib/hitimes/mutexed_stats.rb
|
25
13
|
lib/hitimes/paths.rb
|
@@ -28,17 +16,3 @@ lib/hitimes/timed_metric.rb
|
|
28
16
|
lib/hitimes/timed_value_metric.rb
|
29
17
|
lib/hitimes/value_metric.rb
|
30
18
|
lib/hitimes/version.rb
|
31
|
-
spec/hitimes_spec.rb
|
32
|
-
spec/interval_spec.rb
|
33
|
-
spec/metric_spec.rb
|
34
|
-
spec/mutex_stats_spec.rb
|
35
|
-
spec/paths_spec.rb
|
36
|
-
spec/spec_helper.rb
|
37
|
-
spec/stats_spec.rb
|
38
|
-
spec/timed_metric_spec.rb
|
39
|
-
spec/timed_value_metric_spec.rb
|
40
|
-
spec/value_metric_spec.rb
|
41
|
-
spec/version_spec.rb
|
42
|
-
tasks/default.rake
|
43
|
-
tasks/extension.rake
|
44
|
-
tasks/this.rb
|
data/README.md
CHANGED
@@ -1,17 +1,14 @@
|
|
1
1
|
# Hitimes
|
2
|
+
[![Build Status](https://copiousfreetime.semaphoreci.com/badges/hitimes/branches/main.svg)](https://copiousfreetime.semaphoreci.com/projects/hitimes)
|
2
3
|
|
3
|
-
[
|
4
|
-
|
5
|
-
## Description
|
4
|
+
* [Homepage](http://github.com/copiousfreetime/hitimes)
|
5
|
+
* [Github project](http://github.com/copiousfreetime/hitimes)
|
6
6
|
|
7
|
-
|
7
|
+
## DESCRIPTION
|
8
8
|
|
9
|
-
|
10
|
-
* [Github project](http://github.com.org/copiousfreetime/hitimes)
|
11
|
-
* email jeremy at copiousfreetime dot org
|
12
|
-
* `git clone url git://github.com/copiousfreetime/hitimes.git`
|
9
|
+
A fast, high resolution timer library for recording performance metrics.
|
13
10
|
|
14
|
-
##
|
11
|
+
## TABLE OF CONTENTS
|
15
12
|
|
16
13
|
* [Requirements](#requirements)
|
17
14
|
* [Usage](#usage)
|
@@ -20,13 +17,13 @@ A fast, high resolution timer library for recording peformance metrics.
|
|
20
17
|
* [License](#license)
|
21
18
|
|
22
19
|
|
23
|
-
##
|
20
|
+
## REQUIREMENTS
|
24
21
|
|
25
22
|
Hitimes requires the following to run:
|
26
23
|
|
27
24
|
* Ruby
|
28
25
|
|
29
|
-
##
|
26
|
+
## USAGE
|
30
27
|
|
31
28
|
Hitimes easiest to use when installed with `rubygems`:
|
32
29
|
|
@@ -37,13 +34,13 @@ gem install hitimes
|
|
37
34
|
Or as part of your bundler `Gemfile`:
|
38
35
|
|
39
36
|
```ruby
|
40
|
-
gem
|
37
|
+
gem "hitimes"
|
41
38
|
```
|
42
39
|
|
43
40
|
You can load it with the standard ruby require statement.
|
44
41
|
|
45
42
|
```ruby
|
46
|
-
require
|
43
|
+
require "hitimes"
|
47
44
|
```
|
48
45
|
|
49
46
|
### Interval
|
@@ -53,10 +50,10 @@ Returns the time as seconds.
|
|
53
50
|
|
54
51
|
```ruby
|
55
52
|
duration = Hitimes::Interval.measure do
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
53
|
+
1_000_000.times do |x|
|
54
|
+
2 + 2
|
55
|
+
end
|
56
|
+
end
|
60
57
|
|
61
58
|
puts duration # => 0.047414297 (seconds)
|
62
59
|
```
|
@@ -66,7 +63,7 @@ puts duration # => 0.047414297 (seconds)
|
|
66
63
|
Use a `Hitimes::TimedMetric` to calculate statistics about an iterative operation
|
67
64
|
|
68
65
|
```ruby
|
69
|
-
timed_metric = Hitimes::TimedMetric.new(
|
66
|
+
timed_metric = Hitimes::TimedMetric.new("operation on items")
|
70
67
|
```
|
71
68
|
|
72
69
|
Explicitly use `start` and `stop`:
|
@@ -84,7 +81,8 @@ value of the block.
|
|
84
81
|
|
85
82
|
```ruby
|
86
83
|
collection.each do |item|
|
87
|
-
result_of_do_something = timed_metric.measure { do_something(
|
84
|
+
result_of_do_something = timed_metric.measure { do_something(item) }
|
85
|
+
# do something with result_of_do_something
|
88
86
|
end
|
89
87
|
```
|
90
88
|
And then look at the stats
|
@@ -96,15 +94,16 @@ puts timed_metric.min
|
|
96
94
|
puts timed_metric.stddev
|
97
95
|
puts timed_metric.rate
|
98
96
|
```
|
97
|
+
|
99
98
|
### ValueMetric
|
100
99
|
|
101
100
|
Use a `Hitimes::ValueMetric` to calculate statistics about measured samples.
|
102
101
|
|
103
102
|
``` ruby
|
104
|
-
value_metric = Hitimes::ValueMetric.new(
|
103
|
+
value_metric = Hitimes::ValueMetric.new("size of thing")
|
105
104
|
loop do
|
106
105
|
# ... do stuff changing sizes of 'thing'
|
107
|
-
value_metric.measure(
|
106
|
+
value_metric.measure(thing.size)
|
108
107
|
# ... do other stuff that may change size of thing
|
109
108
|
end
|
110
109
|
|
@@ -120,12 +119,12 @@ puts value_metric.rate
|
|
120
119
|
Use a `Hitimes::TimedValueMetric` to calculate statistics about batches of samples.
|
121
120
|
|
122
121
|
``` ruby
|
123
|
-
timed_value_metric = Hitimes::TimedValueMetric.new(
|
124
|
-
loop do
|
122
|
+
timed_value_metric = Hitimes::TimedValueMetric.new("batch times")
|
123
|
+
loop do
|
125
124
|
batch = ... # get a batch of things
|
126
125
|
timed_value_metric.start
|
127
126
|
# .. do something with batch
|
128
|
-
timed_value_metric.stop(
|
127
|
+
timed_value_metric.stop(batch.size)
|
129
128
|
end
|
130
129
|
|
131
130
|
puts timed_value_metric.rate
|
@@ -143,60 +142,46 @@ puts timed_value_metric.value_stats.stddev
|
|
143
142
|
|
144
143
|
### Implementation details
|
145
144
|
|
146
|
-
Hitimes
|
145
|
+
Hitimes uses the internal ruby `Process::clock_gettime()` to
|
147
146
|
get the highest granularity time increment possible. Generally this is
|
148
|
-
nanosecond resolution, or whatever the hardware
|
149
|
-
|
150
|
-
It currently supports any of the following systems:
|
147
|
+
nanosecond resolution, or whatever the hardware in the CPU supports.
|
151
148
|
|
152
|
-
|
153
|
-
* Mac OS X
|
154
|
-
* Windows
|
155
|
-
* JRuby
|
156
|
-
|
157
|
-
## Support
|
149
|
+
## SUPPORT
|
158
150
|
|
159
151
|
Hitimes is supported on whatever versions of ruby are currently supported.
|
160
152
|
Hitimes also follows [semantic versioning](http://semver.org/).
|
161
153
|
|
162
154
|
The current officially supported versions of Ruby are:
|
163
155
|
|
164
|
-
* MRI Ruby (all platforms)
|
165
|
-
* JRuby 9.
|
156
|
+
* MRI Ruby (all platforms) 3.0 - current
|
157
|
+
* JRuby 9.4.x.x
|
158
|
+
* Truffleruby 24
|
166
159
|
|
167
|
-
Unofficially supported versions,
|
168
|
-
|
169
|
-
|
160
|
+
Unofficially supported versions, any version of MRI from Ruby 2.1 and up. Since
|
161
|
+
the C Extension has been removed Hitimes should work with any ruby that is 2.1
|
162
|
+
or greater as that is when `Process.clock_gettime()` was implemented.
|
170
163
|
|
171
|
-
|
172
|
-
|
173
|
-
* Ruby 1.8 and 1.9 for windows are supported in hitimes version 1.2.4 or earlier
|
174
|
-
* JRuby - I think everything back to 1.4
|
175
|
-
* Rubinius
|
164
|
+
For versions of Ruby before 2.1 please use Hitimes 1.3, the extension code is
|
165
|
+
still in there and they should still work.
|
176
166
|
|
177
|
-
##
|
167
|
+
## CONTRIBUTING
|
178
168
|
|
179
|
-
Please read
|
169
|
+
Please read [CONTRIBUTING.md](CONTRIBUTING.md) for instructions on development
|
170
|
+
and bug reporting.
|
180
171
|
|
181
172
|
## Credits
|
182
173
|
|
183
|
-
* [Bruce Williams](https://github.com/bruce) for suggesting the idea
|
174
|
+
* [Bruce Williams](https://github.com/bruce) for suggesting the idea.
|
175
|
+
* [Benoit Daloze](https://github.com/eregon) and [Thomas Hurst](https://github.com/Freaky) for conversations around clock_ids.
|
184
176
|
|
185
177
|
## License
|
186
178
|
|
187
179
|
Hitimes is licensed under the [ISC](https://opensource.org/licenses/ISC)
|
188
180
|
license.
|
189
181
|
|
190
|
-
|
191
|
-
|
192
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
193
|
-
purpose with or without fee is hereby granted, provided that the above
|
194
|
-
copyright notice and this permission notice appear in all copies.
|
182
|
+
## Related Works
|
195
183
|
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
201
|
-
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
202
|
-
PERFORMANCE OF THIS SOFTWARE.
|
184
|
+
* [monotime](https://github.com/Freaky/monotime) - A sensible interface to Ruby's monotonic clock.
|
185
|
+
* [concurrent-ruby](https://github.com/ruby-concurrency/concurrent-ruby) - [Concurrent.monotonic_time](https://github.com/ruby-concurrency/concurrent-ruby) is a straight pass through to `Process.clock_gettime(Process::CLOCK_MONOTONIC,...)`.
|
186
|
+
* [Instant](https://doc.rust-lang.org/src/std/time.rs.html) - The rust equivalent.
|
187
|
+
* [time.Now](https://pkg.go.dev/time) - The go monotonic time interface is part of this package.
|
data/hitimes.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# DO NOT EDIT - This file is automatically generated
|
2
|
+
# Make changes to Manifest.txt and/or Rakefile and regenerate
|
3
|
+
# -*- encoding: utf-8 -*-
|
4
|
+
# stub: hitimes 3.0.0 ruby lib
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "hitimes".freeze
|
8
|
+
s.version = "3.0.0".freeze
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
11
|
+
s.metadata = { "bug_tracker_uri" => "https://github.com/copiousfreetime/hitimes/issues", "changelog_uri" => "https://github.com/copiousfreetime/hitimes/blob/master/HISTORY.md", "homepage_uri" => "https://github.com/copiousfreetime/hitimes", "source_code_uri" => "https://github.com/copiousfreetime/hitimes" } if s.respond_to? :metadata=
|
12
|
+
s.require_paths = ["lib".freeze]
|
13
|
+
s.authors = ["Jeremy Hinegardner".freeze]
|
14
|
+
s.bindir = "exe".freeze
|
15
|
+
s.date = "2024-05-01"
|
16
|
+
s.description = "A fast, high resolution timer library for recording performance metrics.".freeze
|
17
|
+
s.email = "jeremy@copiousfreetime.org".freeze
|
18
|
+
s.extra_rdoc_files = ["CONTRIBUTING.md".freeze, "HISTORY.md".freeze, "LICENSE.txt".freeze, "Manifest.txt".freeze, "README.md".freeze]
|
19
|
+
s.files = ["CONTRIBUTING.md".freeze, "HISTORY.md".freeze, "LICENSE.txt".freeze, "Manifest.txt".freeze, "README.md".freeze, "hitimes.gemspec".freeze, "lib/hitimes.rb".freeze, "lib/hitimes/initialize.rb".freeze, "lib/hitimes/instant.rb".freeze, "lib/hitimes/interval.rb".freeze, "lib/hitimes/metric.rb".freeze, "lib/hitimes/mutexed_stats.rb".freeze, "lib/hitimes/paths.rb".freeze, "lib/hitimes/stats.rb".freeze, "lib/hitimes/timed_metric.rb".freeze, "lib/hitimes/timed_value_metric.rb".freeze, "lib/hitimes/value_metric.rb".freeze, "lib/hitimes/version.rb".freeze]
|
20
|
+
s.homepage = "http://github.com/copiousfreetime/hitimes".freeze
|
21
|
+
s.licenses = ["ISC".freeze]
|
22
|
+
s.rdoc_options = ["--main".freeze, "README.md".freeze, "--markup".freeze, "tomdoc".freeze]
|
23
|
+
s.required_ruby_version = Gem::Requirement.new(">= 3.0.0".freeze)
|
24
|
+
s.rubygems_version = "3.5.9".freeze
|
25
|
+
s.summary = "A fast, high resolution timer library for recording performance metrics.".freeze
|
26
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Hitimes
|
4
|
+
# Internal: Internal setup that is done when the library is loaded
|
5
|
+
#
|
6
|
+
# We want to determine what clock to use for this machine. So we need to
|
7
|
+
# introspect the ruby environment and then setup some initial constants. These
|
8
|
+
# methods are used in lib/hitimes/instant.rb to help setup the CLOCK_ID
|
9
|
+
# constant at load time.
|
10
|
+
#
|
11
|
+
module Initialize
|
12
|
+
#
|
13
|
+
# After a fair bit of experimentaiton, it seems that the only clock_ids that
|
14
|
+
# are of any use are the following:
|
15
|
+
#
|
16
|
+
# POSIX:
|
17
|
+
#
|
18
|
+
# CLOCK_REALTIME A settable system-wide real-time clock. Measures
|
19
|
+
# wall-clock time. Affected by system jumps in time,
|
20
|
+
# adjtime(3), and NTP.
|
21
|
+
#
|
22
|
+
# CLOCK_MONOTONIC A nonsettable system-wide clock that represent
|
23
|
+
# monotomic time since some unspecified point in the
|
24
|
+
# past. Not affected by jumps in system time, but is
|
25
|
+
# affectd by adjtime(3) and NTP.
|
26
|
+
#
|
27
|
+
# Darwin:
|
28
|
+
#
|
29
|
+
# CLOCK_MONOTONIC_RAW clock that increments monotonically, tracking the
|
30
|
+
# time since an arbitrary point like CLOCK_MONOTONIC.
|
31
|
+
# However, this clock is unaffected by frequency or
|
32
|
+
# time adjustments.
|
33
|
+
#
|
34
|
+
# CLOCK_UPTIME_RAW clock that increments monotonically, in the same manner
|
35
|
+
# as CLOCK_MONOTONIC_RAW, but that does not increment
|
36
|
+
# while the system is asleep. The returned value is
|
37
|
+
# identical to the result of mach_absolute_time()
|
38
|
+
# after the appropriate mach_timebase conversion is applied.
|
39
|
+
#
|
40
|
+
# Linux:
|
41
|
+
#
|
42
|
+
# CLOCK_MONOTONIC_RAW Similar to CLOCK_MONOTONIC, but provides access to
|
43
|
+
# a raw hardware-based time that is not subject to NTP
|
44
|
+
# adjustments or the incremental adjustments performed
|
45
|
+
# by adjtime(3)
|
46
|
+
#
|
47
|
+
# CLOCK_BOOTTIME Identical to CLOCK_MONOTONIC, except it also includes any
|
48
|
+
# time that the system is suspended.
|
49
|
+
#
|
50
|
+
# *BSD:
|
51
|
+
#
|
52
|
+
# All the BSDs seem to have CLOCK_MONOTONIC and CLOCK_REALTIME although on
|
53
|
+
# NetBSD CLOCK_MONOTONIC is not affected by adjtime(2). It is unclear if
|
54
|
+
# they are affected by adjtime(2) on FreeBSD, OpenBSD, or DragonFlyBSD. -
|
55
|
+
# at least according to the man pages.
|
56
|
+
#
|
57
|
+
# What this boils down to as that pretty much all systems have CLOCK_REALTIME
|
58
|
+
# and CLOCK_MONOTONIC. The other clocks are system specific and may or may
|
59
|
+
# not exist. We'll try to use the most accurate clock available.
|
60
|
+
#
|
61
|
+
# So we'll try to use the following clocks in order of preference:
|
62
|
+
#
|
63
|
+
# On Linux and Darwin
|
64
|
+
# CLOCK_MONOTONIC_RAW, CLOCK_MONOTONIC, CLOCK_REALTIME
|
65
|
+
#
|
66
|
+
# Everyone else:
|
67
|
+
# CLOCK_MONOTONIC, CLOCK_REALTIME
|
68
|
+
#
|
69
|
+
# So in reality, well just test for constants on all of the above and use the
|
70
|
+
# first one that exists.
|
71
|
+
#
|
72
|
+
# If CLOCK_REALTIME is chose, we will dump a warning to the user.
|
73
|
+
# And if we can't finde one, which is really, really odd, we'll raise an exception.
|
74
|
+
POTENTIAL_CLOCK_IDS = %i[CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC CLOCK_REALTIME].freeze
|
75
|
+
def determine_clock_id(potential_ids = POTENTIAL_CLOCK_IDS)
|
76
|
+
sym = potential_ids.find { |id| Process.const_defined?(id) }
|
77
|
+
|
78
|
+
unless sym
|
79
|
+
raise Hitimes::Error, <<~ERROR
|
80
|
+
Unable to find a high resolution clock at all. THIS IS A BUG!!
|
81
|
+
|
82
|
+
RUBY_DESCRIPTION: #{RUBY_DESCRIPTION}
|
83
|
+
|
84
|
+
Please report this bug to the hitimes issue tracker at
|
85
|
+
https://github.com/copiousfreetime/hitimes/issues
|
86
|
+
ERROR
|
87
|
+
end
|
88
|
+
|
89
|
+
if sym == :CLOCK_REALTIME
|
90
|
+
warn <<~TXT
|
91
|
+
Unable to find a high resolution clock. Using CLOCK_REALTIME for timing.
|
92
|
+
|
93
|
+
RUBY_DESCRIPTION: #{RUBY_DESCRIPTION}
|
94
|
+
|
95
|
+
Please report the above information to the hitimes issue tracker at
|
96
|
+
https://github.com/copiousfreetime/hitimes/issues
|
97
|
+
TXT
|
98
|
+
end
|
99
|
+
|
100
|
+
Process.const_get(sym)
|
101
|
+
end
|
102
|
+
module_function :determine_clock_id
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "hitimes/initialize"
|
4
|
+
|
5
|
+
# Hitimes Constants and module methods
|
6
|
+
#
|
7
|
+
module Hitimes
|
8
|
+
# Public: The clock_id to use in Process.clock_gettime
|
9
|
+
CLOCK_ID = Initialize.determine_clock_id.freeze
|
10
|
+
|
11
|
+
# Internal: The fraction of second of a nanosecond
|
12
|
+
NANOSECONDS_PER_SECOND = 1e9
|
13
|
+
|
14
|
+
# Public: Get the raw instant
|
15
|
+
#
|
16
|
+
# Examples:
|
17
|
+
#
|
18
|
+
# Hitimes.raw_instant
|
19
|
+
#
|
20
|
+
# Returns the raw instant value
|
21
|
+
def raw_instant
|
22
|
+
Process.clock_gettime(::Hitimes::CLOCK_ID, :nanosecond)
|
23
|
+
end
|
24
|
+
module_function :raw_instant
|
25
|
+
|
26
|
+
# Internal: The human readable clock name of the CLOCK_ID as a string
|
27
|
+
#
|
28
|
+
# Returns the clock name as a String
|
29
|
+
def clock_name
|
30
|
+
case CLOCK_ID
|
31
|
+
when Symbol
|
32
|
+
CLOCK_ID.to_s
|
33
|
+
else
|
34
|
+
const = Process.constants.grep(/CLOCK/).find do |id|
|
35
|
+
Process.const_get(id) == CLOCK_ID
|
36
|
+
end
|
37
|
+
"Process::#{const}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
module_function :clock_name
|
41
|
+
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (c) 2008 Jeremy Hinegardner
|
4
|
+
# All rights reserved. See LICENSE and/or COPYING for details.
|
5
|
+
#
|
6
|
+
module Hitimes
|
7
|
+
# This is the lowest level timing mechanism available. It allows for easy
|
8
|
+
# measuring based upon a block:
|
9
|
+
#
|
10
|
+
# duration = Interval.measure { ... }
|
11
|
+
#
|
12
|
+
# Or measuring something specifically
|
13
|
+
#
|
14
|
+
# interval = Interval.new
|
15
|
+
# interval.start
|
16
|
+
# duration = interval.stop
|
17
|
+
#
|
18
|
+
# Allocating and starting an interval can be done in one method call with
|
19
|
+
#
|
20
|
+
# interval = Interval.now
|
21
|
+
#
|
22
|
+
# Interval is useful when you only need to track a single interval of time, or
|
23
|
+
# if you do not want to track statistics about an operation.
|
24
|
+
class Interval
|
25
|
+
# Public: The integer representing the start instant of the Interval. This
|
26
|
+
# valuea is not useful on its own. It is a platform dependent value.
|
27
|
+
attr_reader :start_instant
|
28
|
+
|
29
|
+
# Public: The integer representing the stop instant of the Interval. This
|
30
|
+
# value is not useful on its own. It is a platform dependent value.
|
31
|
+
attr_reader :stop_instant
|
32
|
+
|
33
|
+
def initialize(start = nil, stop = nil)
|
34
|
+
@start_instant = start
|
35
|
+
@stop_instant = stop
|
36
|
+
@duration = -Float::INFINITY
|
37
|
+
end
|
38
|
+
|
39
|
+
# call-seq:
|
40
|
+
# Interval.now -> Interval
|
41
|
+
#
|
42
|
+
# Create an interval that has already started
|
43
|
+
#
|
44
|
+
def self.now
|
45
|
+
Interval.new(Hitimes.raw_instant)
|
46
|
+
end
|
47
|
+
|
48
|
+
# call-seq:
|
49
|
+
# Interval.measure { } -> Float
|
50
|
+
#
|
51
|
+
# Times the execution of the block returning the number of seconds it took
|
52
|
+
def self.measure
|
53
|
+
raise Error, "No block given to Interval.measure" unless block_given?
|
54
|
+
|
55
|
+
interval = Interval.now
|
56
|
+
yield
|
57
|
+
interval.stop
|
58
|
+
|
59
|
+
interval.duration
|
60
|
+
end
|
61
|
+
|
62
|
+
# call-seq:
|
63
|
+
# interval.split -> Interval
|
64
|
+
#
|
65
|
+
# Immediately stop the current interval and start a new interval that has a
|
66
|
+
# start_instant equivalent to the stop_interval of self.
|
67
|
+
def split
|
68
|
+
@stop_instant = ::Hitimes.raw_instant
|
69
|
+
Interval.new(@stop_instant)
|
70
|
+
end
|
71
|
+
|
72
|
+
# call-seq:
|
73
|
+
# interval.start -> boolean
|
74
|
+
#
|
75
|
+
# mark the start of the interval. Calling start on an already started
|
76
|
+
# interval has no effect. An interval can only be started once. If the
|
77
|
+
# interval is truely started +true+ is returned otherwise +false+.
|
78
|
+
def start
|
79
|
+
return false if started?
|
80
|
+
|
81
|
+
@start_instant = ::Hitimes.raw_instant
|
82
|
+
true
|
83
|
+
end
|
84
|
+
|
85
|
+
# call-seq:
|
86
|
+
# interval.stop -> bool or Float
|
87
|
+
#
|
88
|
+
# mark the stop of the interval. Calling stop on an already stopped interval
|
89
|
+
# has no effect. An interval can only be stopped once. If the interval is
|
90
|
+
# truely stopped then the duration is returned, otherwise +false+.
|
91
|
+
def stop
|
92
|
+
raise Error, "Attempt to stop an interval that has not started" unless started?
|
93
|
+
return false if stopped?
|
94
|
+
|
95
|
+
@stop_instant = ::Hitimes.raw_instant
|
96
|
+
|
97
|
+
duration
|
98
|
+
end
|
99
|
+
|
100
|
+
# call-seq:
|
101
|
+
# interval.duration_so_far -> Float or false
|
102
|
+
#
|
103
|
+
# return how the duration so far. This will return the duration from the time
|
104
|
+
# the Interval was started if the interval is running, otherwise it will return
|
105
|
+
# false.
|
106
|
+
def duration_so_far
|
107
|
+
return false unless running?
|
108
|
+
|
109
|
+
raw = Hitimes.raw_instant
|
110
|
+
calculate_duration(@start_instant, raw)
|
111
|
+
end
|
112
|
+
|
113
|
+
# call-seq:
|
114
|
+
# interval.started? -> boolean
|
115
|
+
#
|
116
|
+
# returns whether or not the interval has been started
|
117
|
+
def started?
|
118
|
+
!!@start_instant
|
119
|
+
end
|
120
|
+
|
121
|
+
# call-seq:
|
122
|
+
# interval.stopped? -> boolean
|
123
|
+
#
|
124
|
+
# returns whether or not the interval has been stopped
|
125
|
+
def stopped?
|
126
|
+
!!@stop_instant
|
127
|
+
end
|
128
|
+
|
129
|
+
# call-seq:
|
130
|
+
# interval.running? -> boolean
|
131
|
+
#
|
132
|
+
# returns whether or not the interval is running or not. This means that it
|
133
|
+
# has started, but not stopped.
|
134
|
+
#
|
135
|
+
def running?
|
136
|
+
started? && !stopped?
|
137
|
+
end
|
138
|
+
|
139
|
+
# call-seq:
|
140
|
+
# interval.duration -> Float
|
141
|
+
# interval.to_f -> Float
|
142
|
+
# interval.to_seconds -> Float
|
143
|
+
# interval.length -> Float
|
144
|
+
#
|
145
|
+
# Returns the Float value of the interval, the value is in seconds. If the
|
146
|
+
# interval has not had stop called yet, it will report the number of seconds
|
147
|
+
# in the interval up to the current point in time.
|
148
|
+
#
|
149
|
+
# Raises Error if duration is called on an interval that has not started yet.
|
150
|
+
#
|
151
|
+
def duration
|
152
|
+
raise Error, "Attempt to report a duration on an interval that has not started" unless started?
|
153
|
+
|
154
|
+
return duration_so_far unless stopped?
|
155
|
+
|
156
|
+
@duration = calculate_duration(@start_instant, @stop_instant) if @duration.negative?
|
157
|
+
|
158
|
+
@duration
|
159
|
+
end
|
160
|
+
|
161
|
+
alias to_f duration
|
162
|
+
alias to_seconds duration
|
163
|
+
alias length duration
|
164
|
+
|
165
|
+
private
|
166
|
+
|
167
|
+
def calculate_duration(start, stop)
|
168
|
+
(stop - start) / ::Hitimes::NANOSECONDS_PER_SECOND
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|