hitimes 1.3.1 → 3.0.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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +1 -12
  3. data/HISTORY.md +26 -2
  4. data/Manifest.txt +5 -31
  5. data/README.md +44 -59
  6. data/hitimes.gemspec +26 -0
  7. data/lib/hitimes/initialize.rb +104 -0
  8. data/lib/hitimes/instant.rb +41 -0
  9. data/lib/hitimes/interval.rb +171 -0
  10. data/lib/hitimes/metric.rb +18 -22
  11. data/lib/hitimes/mutexed_stats.rb +3 -20
  12. data/lib/hitimes/paths.rb +16 -14
  13. data/lib/hitimes/stats.rb +119 -22
  14. data/lib/hitimes/timed_metric.rb +43 -42
  15. data/lib/hitimes/timed_value_metric.rb +43 -43
  16. data/lib/hitimes/value_metric.rb +16 -15
  17. data/lib/hitimes/version.rb +3 -1
  18. data/lib/hitimes.rb +14 -41
  19. metadata +24 -157
  20. data/Rakefile +0 -28
  21. data/examples/benchmarks.rb +0 -113
  22. data/examples/stats.rb +0 -31
  23. data/ext/hitimes/c/extconf.rb +0 -24
  24. data/ext/hitimes/c/hitimes.c +0 -37
  25. data/ext/hitimes/c/hitimes_instant_clock_gettime.c +0 -28
  26. data/ext/hitimes/c/hitimes_instant_osx.c +0 -48
  27. data/ext/hitimes/c/hitimes_instant_windows.c +0 -27
  28. data/ext/hitimes/c/hitimes_interval.c +0 -370
  29. data/ext/hitimes/c/hitimes_interval.h +0 -73
  30. data/ext/hitimes/c/hitimes_stats.c +0 -269
  31. data/ext/hitimes/c/hitimes_stats.h +0 -30
  32. data/ext/hitimes/java/src/hitimes/Hitimes.java +0 -63
  33. data/ext/hitimes/java/src/hitimes/HitimesInterval.java +0 -176
  34. data/ext/hitimes/java/src/hitimes/HitimesService.java +0 -16
  35. data/ext/hitimes/java/src/hitimes/HitimesStats.java +0 -112
  36. data/spec/hitimes_spec.rb +0 -24
  37. data/spec/interval_spec.rb +0 -136
  38. data/spec/metric_spec.rb +0 -28
  39. data/spec/mutex_stats_spec.rb +0 -36
  40. data/spec/paths_spec.rb +0 -11
  41. data/spec/spec_helper.rb +0 -11
  42. data/spec/stats_spec.rb +0 -98
  43. data/spec/timed_metric_spec.rb +0 -155
  44. data/spec/timed_value_metric_spec.rb +0 -171
  45. data/spec/value_metric_spec.rb +0 -108
  46. data/spec/version_spec.rb +0 -7
  47. data/tasks/default.rake +0 -242
  48. data/tasks/extension.rake +0 -38
  49. data/tasks/this.rb +0 -208
  50. /data/{LICENSE → LICENSE.txt} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4e479c2fbfddbd9d35a7f9bcc4580b265f43cd9fa46a7a986e1d10401c58b882
4
- data.tar.gz: 5751466c5f9a518a607b4f14df5e368dd85d990fccbc665f6d080b5435982b4d
3
+ metadata.gz: d79a16734531380e103efb7bf1af93e5c4e465185f5a47f1c0ab6d2dcc8bb5e7
4
+ data.tar.gz: deb8a23bdc8e0f35b6dccbd6fd4535ffdfa4c5bdd11ff44fa488a53baa090245
5
5
  SHA512:
6
- metadata.gz: fabe96db83fec72aac45648908229119bce50fdef39e61fc00f426a7d44ba3da791be416b5e44f0c6bd4cae822e241e152f827c490fb46658946a910ffad6579
7
- data.tar.gz: e1ba6e894dbabf0911df83bbae59a9dfd201b2edfd605a2fe9c27f46e2d5d5bf80105918f3a718df02de0fccf975cc36ada85254b53f949ce78036fe9130d050
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
- * `rake develop` to get started
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
- Rakefile
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
- [![Build Status](https://travis-ci.org/copiousfreetime/hitimes.svg?branch=master)](https://travis-ci.org/copiousfreetime/hitimes)
4
-
5
- ## Description
4
+ * [Homepage](http://github.com/copiousfreetime/hitimes)
5
+ * [Github project](http://github.com/copiousfreetime/hitimes)
6
6
 
7
- A fast, high resolution timer library for recording peformance metrics.
7
+ ## DESCRIPTION
8
8
 
9
- * [Homepage](http://github.com/copiousfreetime/hitimes)
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
- ## Table of Contents
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
- ## Requirements
20
+ ## REQUIREMENTS
24
21
 
25
22
  Hitimes requires the following to run:
26
23
 
27
24
  * Ruby
28
25
 
29
- ## Usage
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 'hitimes'
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 'hitimes'
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
- 1_000_000.times do |x|
57
- 2 + 2
58
- end
59
- end
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('operation on items')
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( item ) }
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( 'size of thing' )
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( thing.size )
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( 'batch times' )
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( batch.size )
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 use the appropriate low-level system call for each operating system to
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 chip in the CPU supports.
149
-
150
- It currently supports any of the following systems:
147
+ nanosecond resolution, or whatever the hardware in the CPU supports.
151
148
 
152
- * any system with the POSIX call `clock_gettime()`
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) 2.3 - 2.6
165
- * JRuby 9.1.17.0, 9.2.X.X
156
+ * MRI Ruby (all platforms) 3.0 - current
157
+ * JRuby 9.4.x.x
158
+ * Truffleruby 24
166
159
 
167
- Unofficially supported versions, these have been supported in the past when they
168
- were the primary rubies around. In all likelihood they still work, but are not
169
- supported.
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
- * MRI Ruby (linux/mac/bsd/unix/etc) - everything from 1.8.7 to 2.2
172
- * MRI Ruby (windows) - 2.0 and up
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
- ## Contributing
167
+ ## CONTRIBUTING
178
168
 
179
- Please read the [CONTRIBUTING.md](CONTRIBUTING.md)
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
- Copyright (c) 2008-2016 Jeremy Hinegardner
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
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
197
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
198
- FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
199
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
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