time_up 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 2814efda7871308dcafe0196407a3bbea424770069d9b998c8728f974a641413
4
+ data.tar.gz: 791e65a388e0d62ece0166a747a20cd41f37259d6283e197ff020a05b6eb3e70
5
+ SHA512:
6
+ metadata.gz: a697b5da2199813b882d8a1b3994670dde64c8ce5adb95b321a8bef3c8892cda9110e778c505e0fd4c327f1956f474be07db9f5fc008926093af9c60c4a8accf
7
+ data.tar.gz: 1b7089abf119e10a4cff97f880d9a05536a960b112ba59a57f6c6d8642771e566b697db88f6d7c7e2fdca73ff0549803864314de7601d0643e0c018cfbc3731e
@@ -0,0 +1,18 @@
1
+ name: Ruby
2
+
3
+ on: [push,pull_request]
4
+
5
+ jobs:
6
+ build:
7
+ runs-on: ubuntu-latest
8
+ steps:
9
+ - uses: actions/checkout@v2
10
+ - name: Set up Ruby
11
+ uses: ruby/setup-ruby@v1
12
+ with:
13
+ ruby-version: 3.0.1
14
+ - name: Run the default task
15
+ run: |
16
+ gem install bundler -v 2.2.15
17
+ bundle install
18
+ bundle exec rake
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ # 0.0.1
2
+
3
+ - Make the gem
4
+
5
+
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ gem "rake"
6
+ gem "minitest"
7
+ gem "standard"
data/Gemfile.lock ADDED
@@ -0,0 +1,48 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ time_up (0.0.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ ast (2.4.2)
10
+ minitest (5.14.4)
11
+ parallel (1.20.1)
12
+ parser (3.0.2.0)
13
+ ast (~> 2.4.1)
14
+ rainbow (3.0.0)
15
+ rake (13.0.6)
16
+ regexp_parser (2.1.1)
17
+ rexml (3.2.5)
18
+ rubocop (1.18.3)
19
+ parallel (~> 1.10)
20
+ parser (>= 3.0.0.0)
21
+ rainbow (>= 2.2.2, < 4.0)
22
+ regexp_parser (>= 1.8, < 3.0)
23
+ rexml
24
+ rubocop-ast (>= 1.7.0, < 2.0)
25
+ ruby-progressbar (~> 1.7)
26
+ unicode-display_width (>= 1.4.0, < 3.0)
27
+ rubocop-ast (1.8.0)
28
+ parser (>= 3.0.1.1)
29
+ rubocop-performance (1.11.4)
30
+ rubocop (>= 1.7.0, < 2.0)
31
+ rubocop-ast (>= 0.4.0)
32
+ ruby-progressbar (1.11.0)
33
+ standard (1.1.5)
34
+ rubocop (= 1.18.3)
35
+ rubocop-performance (= 1.11.4)
36
+ unicode-display_width (2.0.0)
37
+
38
+ PLATFORMS
39
+ arm64-darwin-20
40
+
41
+ DEPENDENCIES
42
+ minitest
43
+ rake
44
+ standard
45
+ time_up!
46
+
47
+ BUNDLED WITH
48
+ 2.2.15
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2021 Test Double, LLC
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,184 @@
1
+ # time_up
2
+
3
+ Ever need to measure the elapsed wall-time for one or more bits of Ruby code,
4
+ but don't necessarily want to reach for
5
+ [Benchmark](https://ruby-doc.org/stdlib-3.0.1/libdoc/benchmark/rdoc/Benchmark.html) or roll your own ad hoc measurement code?
6
+ Try `time_up`!
7
+
8
+ This gem is especially useful for long-running processes (like test suites) that
9
+ have several time-intensive operations that are repeated over time and that you
10
+ want to measure and aggregate. (For example, to see how much time your
11
+ test suite spends creating factories, truncating the database, or invoking a
12
+ critical code path.)
13
+
14
+ ## Install
15
+
16
+ Just run `gem install time_up` or add time_up to your Gemfile:
17
+
18
+ ```ruby
19
+ gem "time_up"
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ Starting a timer is easy! Just call `TimeUp.start`:
25
+
26
+ ```ruby
27
+ # Pass a block and time_up will only count the time while the block executes:
28
+ TimeUp.start(:factories) do
29
+ # … create some factories
30
+ end
31
+
32
+ # Without a block, a started timer will run until you stop it:
33
+ TimeUp.start(:truncation)
34
+ # … truncate some stuff
35
+ TimeUp.stop(:truncation)
36
+ ```
37
+
38
+ To get the total time that's elapsed while the timer has been running, call
39
+ `elapsed`:
40
+
41
+ ```ruby
42
+ slow_time = TimeUp.elapsed(:slow_code_path)
43
+ ```
44
+
45
+ Which will return a `Float` representing the number of seconds that have elapsed
46
+ while the timer is running.
47
+
48
+ Timers aggregate total elapsed time running, just like a digital stopwatch. That
49
+ means if you start a timer after it's been stopped, the additional time will be
50
+ _added_ to the previous elapsed time:
51
+
52
+ ```ruby
53
+ TimeUp.start :eggs
54
+ sleep 1
55
+ puts TimeUp.stop :eggs # => ~1.0
56
+
57
+ TimeUp.start :eggs
58
+ sleep 1
59
+ # To get the elapsed time without necessarily stopping the timer, call `elapsed`
60
+ puts TimeUp.elapsed :eggs # => ~2.0
61
+
62
+ # To reset a timer to 0, call `reset` (if it's running, it'll keep running!)
63
+ TimeUp.reset :eggs
64
+ sleep 5
65
+ puts TimeUp.stop :eggs # => ~5.0
66
+ ```
67
+
68
+ `TimeUp.start` also returns an instance of the named timer, which has its own
69
+ `start`, `stop`, `elaped`, and `reset` methods. If you want to find that
70
+ instance later, you can also call `TimeUp.timer(:some_name)`. So the above
71
+ example could be rewritten as:
72
+
73
+ ```ruby
74
+ egg_timer = TimeUp.start :eggs
75
+ sleep 1
76
+ puts egg_timer.stop # => ~1.0
77
+
78
+ egg_timer.start
79
+ sleep 1
80
+
81
+ # To get the elapsed time without necessarily stopping the timer, call `elapsed`
82
+ puts egg_timer.elapsed # => ~2.0
83
+
84
+ # To reset a timer to 0, call `reset` (if it's running, it'll keep running!)
85
+ egg_timer.reset
86
+ sleep 5
87
+ puts egg_timer.stop # => ~5.0
88
+ ```
89
+
90
+ Finally, if you're juggling a bunch of timers, you can get a summary report of
91
+ them printed for you, like so:
92
+
93
+ ```ruby
94
+ TimeUp.start :roast
95
+ sleep 0.03
96
+ TimeUp.start :veggies
97
+ sleep 0.02
98
+ TimeUp.start :pasta
99
+ sleep 0.01
100
+ TimeUp.stop_all
101
+
102
+ TimeUp.start :souffle
103
+
104
+ TimeUp.print_summary
105
+ ```
106
+
107
+ Which will output something like:
108
+
109
+ ```
110
+ TimeUp timers summary
111
+ ========================
112
+ :roast 0.07267s
113
+ :veggies 0.03760s
114
+ :pasta 0.01257s
115
+ :souffle* 0.00003s
116
+
117
+ * Denotes that the timer is still active
118
+ ```
119
+
120
+ ## API
121
+
122
+ This gem defines a bunch of public methods but they're all pretty short and
123
+ straightforward, so I'd encourage you to [read the code](/lib/time_up.rb).
124
+
125
+ ### `TimeUp` module
126
+
127
+ `TimeUp.start(name, [&blk])` - Starts (or restarts) and returns a named `Timer`
128
+
129
+ `TimeUp.timer(name)` - Returns any a `Timer` instance named `name` or `nil`
130
+
131
+ `TimeUp.stop(name)` - Stops the named timer or raises if it's not defined
132
+
133
+ `TimeUp.elapsed(name)` - Returns a `Float` of the total elapsed seconds that the
134
+ named timer has been running (and raises if no timer is defined with the given
135
+ `name`)
136
+
137
+ `TimeUp.reset(name)` - Resets the named timer's elapsed time to 0, effectively
138
+ restarting it if it's currently running. Raises if the timer isn't defined.
139
+
140
+ `TimeUp.total_elapsed` - Returns a `Float` of the sum of `elapsed` for all the
141
+ timers you've created
142
+
143
+ `TimeUp.all_elapsed` - Returns a hash of timer name keys mapped to their
144
+ `elapsed` values. Handy for grabbing a snapshot of the state of things at a
145
+ particular point in time without stopping all your timers
146
+
147
+ `TimeUp.active_timers` - Returns an array of all timers that are currently
148
+ running. Useful for detecting cases where you might be counting the same time in
149
+ multiple places simultaneously
150
+
151
+ `TimeUp.print_summary([IO])` - Pretty-prints a multi-line summary of all your
152
+ timers to STDOUT (or the provided IO)
153
+
154
+ `TimeUp.stop_all` - Stops all timers
155
+
156
+ `TimeUp.reset_all` - Resets all timers
157
+
158
+ `TimeUp.delete_all` - Stops and resets all timers and deletes any internal
159
+ reference to them
160
+
161
+ ### `TimeUp::Timer` class
162
+
163
+ `start` - Starts the timer
164
+
165
+ `stop` - Stops the timer
166
+
167
+ `elapsed` - A `Float` of the total elapsed seconds the timer has been running
168
+
169
+ `active?` - Returns `true` if the timer is running
170
+
171
+ `reset(force: false)` - Resets the timer to 0 elapsed seconds. If `force` is
172
+ true, will also stop the timer if it's running
173
+
174
+ ## Code of Conduct
175
+
176
+ This project follows Test Double's [code of
177
+ conduct](https://testdouble.com/code-of-conduct) for all community interactions,
178
+ including (but not limited to) one-on-one communications, public posts/comments,
179
+ code reviews, pull requests, and GitHub issues. If violations occur, Test Double
180
+ will take any action they deem appropriate for the infraction, up to and
181
+ including blocking a user from the organization's repositories.
182
+
183
+
184
+
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+ require "standard/rake"
4
+
5
+ Rake::TestTask.new(:test) do |t|
6
+ t.libs << "test"
7
+ t.libs << "lib"
8
+ t.test_files = FileList["test/**/*_test.rb"]
9
+ end
10
+
11
+ task default: [:test, "standard:fix"]
data/bin/console ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+ require "bundler/setup"
3
+ require "time_up"
4
+
5
+ # You can add fixtures and/or initialization code here to make experimenting
6
+ # with your gem easier. You can also use a different console, if you like.
7
+
8
+ # (If you use this, don't forget to add pry to your Gemfile!)
9
+ # require "pry"
10
+ # Pry.start
11
+
12
+ require "irb"
13
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/lib/time_up.rb ADDED
@@ -0,0 +1,136 @@
1
+ require_relative "time_up/version"
2
+
3
+ module TimeUp
4
+ class Error < StandardError; end
5
+
6
+ @timers = {}
7
+ def self.start(name, &blk)
8
+ raise Error.new("Timer name must be a String or Symbol") unless name.is_a?(Symbol) || name.is_a?(String)
9
+ timer = @timers[name] ||= Timer.new(name)
10
+ timer.start
11
+ if blk
12
+ blk.call
13
+ timer.stop
14
+ end
15
+ timer
16
+ end
17
+
18
+ # Delegate methods
19
+ def self.timer(name)
20
+ @timers[name]
21
+ end
22
+
23
+ def self.stop(name)
24
+ __ensure_timer(name)
25
+ @timers[name].stop
26
+ end
27
+
28
+ def self.elapsed(name)
29
+ __ensure_timer(name)
30
+ @timers[name].elapsed
31
+ end
32
+
33
+ def self.reset(name)
34
+ __ensure_timer(name)
35
+ @timers[name].reset
36
+ end
37
+
38
+ # Interrogative methods
39
+ def self.total_elapsed
40
+ @timers.values.sum(&:elapsed)
41
+ end
42
+
43
+ def self.all_elapsed
44
+ @timers.values.map { |timer|
45
+ [timer.name, timer.elapsed]
46
+ }.to_h
47
+ end
48
+
49
+ def self.active_timers
50
+ @timers.values.select(&:active?)
51
+ end
52
+
53
+ def self.print_summary(io = $stdout)
54
+ longest_name_length = @timers.values.map { |t| t.name.inspect.size }.max
55
+ summaries = @timers.values.map { |timer|
56
+ name = "#{timer.name.inspect}#{"*" if timer.active?}".ljust(longest_name_length + 1)
57
+ "#{name}\t#{"%.5f" % timer.elapsed}s"
58
+ }
59
+ io.puts <<~SUMMARY
60
+
61
+ TimeUp timers summary
62
+ ========================
63
+ #{summaries.join("\n")}
64
+
65
+ #{"* Denotes that the timer is still active\n" if @timers.values.any?(&:active?)}
66
+ SUMMARY
67
+ end
68
+
69
+ # Iterative methods
70
+ def self.stop_all
71
+ @timers.values.each(&:stop)
72
+ end
73
+
74
+ def self.reset_all
75
+ @timers.values.each(&:reset)
76
+ end
77
+
78
+ def self.delete_all
79
+ @timers.values.each { |t| t.reset(force: true) }
80
+ @timers = {}
81
+ end
82
+
83
+ # Internal methods
84
+ def self.__ensure_timer(name)
85
+ raise Error.new("No timer named #{name.inspect}") unless @timers[name]
86
+ end
87
+
88
+ class Timer
89
+ attr_reader :name
90
+
91
+ def initialize(name)
92
+ @name = name
93
+ @start_time = nil
94
+ @elapsed = 0.0
95
+ end
96
+
97
+ def start
98
+ @start_time ||= now
99
+ end
100
+
101
+ def stop
102
+ if @start_time
103
+ @elapsed += now - @start_time
104
+ @start_time = nil
105
+ end
106
+ @elapsed
107
+ end
108
+
109
+ def elapsed
110
+ if active?
111
+ @elapsed + (now - @start_time)
112
+ else
113
+ @elapsed
114
+ end
115
+ end
116
+
117
+ def active?
118
+ !!@start_time
119
+ end
120
+
121
+ def reset(force: false)
122
+ if force
123
+ @start_time = nil
124
+ elsif !@start_time.nil?
125
+ @start_time = now
126
+ end
127
+ @elapsed = 0.0
128
+ end
129
+
130
+ private
131
+
132
+ def now
133
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,3 @@
1
+ module TimeUp
2
+ VERSION = "0.0.1"
3
+ end
data/time_up.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ require_relative "lib/time_up/version"
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "time_up"
5
+ spec.version = TimeUp::VERSION
6
+ spec.authors = ["Justin Searls"]
7
+ spec.email = ["searls@gmail.com"]
8
+
9
+ spec.summary = "A little library for managing multiple named timers"
10
+ spec.homepage = "https://github.com/testdouble/time_up"
11
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.4.0")
12
+
13
+ spec.metadata["homepage_uri"] = spec.homepage
14
+ spec.metadata["source_code_uri"] = "https://github.com/testdouble/time_up"
15
+ spec.metadata["changelog_uri"] = "https://github.com/testdouble/time_up/blob/main/CHANGELOG.md"
16
+
17
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
18
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
19
+ end
20
+ spec.bindir = "exe"
21
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+ end
metadata ADDED
@@ -0,0 +1,58 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: time_up
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Justin Searls
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2021-07-15 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description:
14
+ email:
15
+ - searls@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ".github/workflows/main.yml"
21
+ - ".gitignore"
22
+ - CHANGELOG.md
23
+ - Gemfile
24
+ - Gemfile.lock
25
+ - LICENSE.txt
26
+ - README.md
27
+ - Rakefile
28
+ - bin/console
29
+ - bin/setup
30
+ - lib/time_up.rb
31
+ - lib/time_up/version.rb
32
+ - time_up.gemspec
33
+ homepage: https://github.com/testdouble/time_up
34
+ licenses: []
35
+ metadata:
36
+ homepage_uri: https://github.com/testdouble/time_up
37
+ source_code_uri: https://github.com/testdouble/time_up
38
+ changelog_uri: https://github.com/testdouble/time_up/blob/main/CHANGELOG.md
39
+ post_install_message:
40
+ rdoc_options: []
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 2.4.0
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ requirements: []
54
+ rubygems_version: 3.2.15
55
+ signing_key:
56
+ specification_version: 4
57
+ summary: A little library for managing multiple named timers
58
+ test_files: []