time_up 0.0.1

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