hitimes 1.3.1 → 3.0.0

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