time_up 0.0.3 → 0.0.7
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 +4 -4
- data/.standard.yml +1 -0
- data/CHANGELOG.md +13 -0
- data/Gemfile.lock +1 -1
- data/README.md +68 -36
- data/lib/time_up.rb +85 -4
- data/lib/time_up/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c18c0412768d6e182c94ef02f66e630508f5c959f433d1d1ecf322ce16107c3a
|
4
|
+
data.tar.gz: c18ce6ae92e02cd52ddad357d8f542185869d8e6fa5cebf090ee3bc4b576a44c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8a73b80a2193a5df7ce3bae010b109c3e5c34de5329ca34c75cc6d7b296aae395c81ed1488a64e932069c7da8a496ea175d81f6ae4defe214445760c98a01551
|
7
|
+
data.tar.gz: 610cc5554be65e278b2187c56e0d2ebc382b5c916a2e666c39ba84da9ede77bc618ff3c4d58d2df22030bf9a8ad049cbd3eb45827bd0a7c7419e46d8166035f4
|
data/.standard.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby_version: 2.4
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
# 0.0.6
|
2
|
+
|
3
|
+
- Add `TimeUp.all_timers`. It's weird that it's not a thing.
|
4
|
+
|
5
|
+
# 0.0.5
|
6
|
+
|
7
|
+
- Add `median` and `percentile` timer statistics, and added them to
|
8
|
+
`print_detailed_summary`
|
9
|
+
|
10
|
+
# 0.0.4
|
11
|
+
|
12
|
+
- Add `TimeUp.print_detailed_summary`
|
13
|
+
|
1
14
|
# 0.0.3
|
2
15
|
|
3
16
|
- Change the return value of TimeUp.start when passed a block to be the
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -11,6 +11,9 @@ process and that you want to measure in aggregate. (For example, to see how
|
|
11
11
|
much time your test suite spends creating factories, truncating the database, or
|
12
12
|
invoking a critical code path.)
|
13
13
|
|
14
|
+
Here's a [blog post about time_up](https://blog.testdouble.com/posts/2021-07-19-benchmarking-your-ruby-with-time_up/) and
|
15
|
+
a [great example of when it can be useful](https://gist.github.com/searls/feee0b0eac7c329b390fed90c4714afb).
|
16
|
+
|
14
17
|
## Install
|
15
18
|
|
16
19
|
Just run `gem install time_up` or add time_up to your Gemfile:
|
@@ -107,7 +110,7 @@ TimeUp.print_summary
|
|
107
110
|
Which will output something like:
|
108
111
|
|
109
112
|
```
|
110
|
-
TimeUp
|
113
|
+
TimeUp summary
|
111
114
|
========================
|
112
115
|
:roast 0.07267s
|
113
116
|
:veggies 0.03760s
|
@@ -117,10 +120,27 @@ TimeUp timers summary
|
|
117
120
|
* Denotes that the timer is still active
|
118
121
|
```
|
119
122
|
|
123
|
+
And if you're calling the timers multiple times and want to see some basic
|
124
|
+
statistics in the print-out, you can call `TimeUp.print_detailed_summary`, which
|
125
|
+
will produce this:
|
126
|
+
|
127
|
+
```
|
128
|
+
=============================================================================
|
129
|
+
Name | Elapsed | Count | Min | Max | Mean | Median | 95th %
|
130
|
+
-----------------------------------------------------------------------------
|
131
|
+
:roast | 0.08454 | 3 | 0.00128 | 0.07280 | 0.02818 | 0.01046 | 0.06657
|
132
|
+
:veggies | 0.03779 | 1 | 0.03779 | 0.03779 | 0.03779 | 0.03779 | 0.03779
|
133
|
+
:pasta | 0.01260 | 11 | 0.00000 | 0.01258 | 0.00115 | 0.00000 | 0.00630
|
134
|
+
:souffle* | 0.00024 | 1 | 0.00024 | 0.00025 | 0.00025 | 0.00025 | 0.00026
|
135
|
+
|
136
|
+
* Denotes that the timer is still active
|
137
|
+
```
|
138
|
+
|
120
139
|
## API
|
121
140
|
|
122
141
|
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
|
142
|
+
straightforward, so when in doubt, I'd encourage you to [read the
|
143
|
+
code](/lib/time_up.rb).
|
124
144
|
|
125
145
|
### `TimeUp` module
|
126
146
|
|
@@ -128,51 +148,60 @@ straightforward, so I'd encourage you to [read the code](/lib/time_up.rb).
|
|
128
148
|
if it doesn't exist)
|
129
149
|
|
130
150
|
`TimeUp.start(name, [&blk])` - Starts (or restarts) a named
|
131
|
-
[Timer](#timeuptimer-class). If passed
|
132
|
-
|
151
|
+
[Timer](#timeuptimer-class). If passed a block, will return whatever the block
|
152
|
+
evaluates to. If called without a block, it will return the timer object
|
133
153
|
|
134
|
-
`TimeUp.stop(name)` - Stops the named timer
|
154
|
+
`TimeUp.stop(name)` - Stops the named timer
|
135
155
|
|
136
156
|
`TimeUp.reset(name)` - Resets the named timer's elapsed time to 0, effectively
|
137
|
-
restarting it if it's currently running
|
157
|
+
restarting it if it's currently running
|
138
158
|
|
139
159
|
`TimeUp.elapsed(name)` - Returns a `Float` of the total elapsed seconds that the
|
140
|
-
named timer has been running
|
141
|
-
`name`)
|
160
|
+
named timer has been running
|
142
161
|
|
143
162
|
`TimeUp.timings(name)` - Returns an array of each recorded start-to-stop
|
144
|
-
duration
|
163
|
+
duration (including the current one, if the timer is running) of the named timer
|
164
|
+
|
165
|
+
`TimeUp.count(name)` - The number of times the timer has been started (including
|
166
|
+
the current timing, if the timer is running)
|
167
|
+
|
168
|
+
`TimeUp.min(name)` - The shortest recording by the timer
|
145
169
|
|
146
|
-
`TimeUp.
|
147
|
-
stopped (including the current timing, if active)
|
170
|
+
`TimeUp.max(name)` - The longest recording by the timer
|
148
171
|
|
149
|
-
`TimeUp.
|
150
|
-
one, if active)
|
172
|
+
`TimeUp.mean(name)` - The arithmetic mean of all recordings by the timer
|
151
173
|
|
152
|
-
`TimeUp.
|
153
|
-
one, if active)
|
174
|
+
`TimeUp.median(name)` - The median of all recordings by the timer
|
154
175
|
|
155
|
-
`TimeUp.
|
176
|
+
`TimeUp.percentile(name, percent)` - The timing for the given
|
177
|
+
[percentile](https://en.wikipedia.org/wiki/Percentile) of all recordings by the
|
178
|
+
timer
|
156
179
|
|
157
|
-
`TimeUp.total_elapsed` - Returns a `Float` of the sum of `elapsed`
|
158
|
-
timers you've created
|
180
|
+
`TimeUp.total_elapsed` - Returns a `Float` of the sum of `elapsed` across all
|
181
|
+
the timers you've created (note that because you can easily run multiple logical
|
182
|
+
timers simultaneously, this figure may exceed the total time spent by the
|
183
|
+
computer)
|
159
184
|
|
160
|
-
`TimeUp.all_elapsed` - Returns a
|
161
|
-
`elapsed` values. Handy for grabbing a snapshot of the state of
|
162
|
-
|
185
|
+
`TimeUp.all_elapsed` - Returns a Hash of timer name keys mapped to their
|
186
|
+
`elapsed` values. Handy for grabbing a reference to a snapshot of the state of
|
187
|
+
things without requiring you to stop your timers
|
163
188
|
|
164
|
-
`TimeUp.all_stats` - Returns a
|
165
|
-
hash of their basic statistics (elapsed
|
166
|
-
and mean)
|
189
|
+
`TimeUp.all_stats` - Returns a Hash of timer name keys mapped to another
|
190
|
+
hash of their basic statistics (`elapsed`, `count`, `min`, `max`,
|
191
|
+
and `mean`)
|
167
192
|
|
168
|
-
`TimeUp.active_timers` - Returns an
|
169
|
-
running. Useful for detecting cases where you might be
|
170
|
-
|
193
|
+
`TimeUp.active_timers` - Returns an Array of all timers that are currently
|
194
|
+
running. Useful for detecting cases where you might be keeping time in multiple
|
195
|
+
places simultaneously
|
171
196
|
|
172
197
|
`TimeUp.print_summary([io])` - Pretty-prints a multi-line summary of all your
|
173
|
-
timers to standard output (or the provided
|
198
|
+
timers' total elapsed times to standard output (or the provided
|
174
199
|
[IO](https://ruby-doc.org/core-3.0.1/IO.html))
|
175
200
|
|
201
|
+
`TimeUp.print_detailed_summary([io])` - Pretty-prints a multi-line summary of
|
202
|
+
all your timers' elapsed times and basic statistics to standard output (or the
|
203
|
+
provided [IO](https://ruby-doc.org/core-3.0.1/IO.html))
|
204
|
+
|
176
205
|
`TimeUp.stop_all` - Stops all timers
|
177
206
|
|
178
207
|
`TimeUp.reset_all` - Resets all timers
|
@@ -188,20 +217,23 @@ reference to them
|
|
188
217
|
|
189
218
|
`elapsed` - A `Float` of the total elapsed seconds the timer has been running
|
190
219
|
|
191
|
-
`timings` - Returns an
|
192
|
-
timer (including the current one, if
|
220
|
+
`timings` - Returns an Array of each recorded start-to-stop duration of the
|
221
|
+
timer (including the current one, if the timer is running)
|
193
222
|
|
194
|
-
`count` - The number of times the timer has been started and stopped
|
195
|
-
the current timing, if active)
|
223
|
+
`count` - The number of times the timer has been started and stopped
|
196
224
|
|
197
|
-
`min` - The shortest recording of the timer
|
198
|
-
active)
|
225
|
+
`min` - The shortest recording of the timer
|
199
226
|
|
200
|
-
`max` - The longest recording of the timer
|
201
|
-
active)
|
227
|
+
`max` - The longest recording of the timer
|
202
228
|
|
203
229
|
`mean` - The arithmetic mean of all recorded durations of the timer
|
204
230
|
|
231
|
+
`median(name)` - The median of all recordings by the timer
|
232
|
+
|
233
|
+
`percentile(name, percent)` - The timing for the given
|
234
|
+
[percentile](https://en.wikipedia.org/wiki/Percentile) of all recordings by the
|
235
|
+
timer
|
236
|
+
|
205
237
|
`active?` - Returns `true` if the timer is running
|
206
238
|
|
207
239
|
`reset(force: false)` - Resets the timer to 0 elapsed seconds. If `force` is
|
data/lib/time_up.rb
CHANGED
@@ -22,7 +22,8 @@ module TimeUp
|
|
22
22
|
:count,
|
23
23
|
:min,
|
24
24
|
:max,
|
25
|
-
:mean
|
25
|
+
:mean,
|
26
|
+
:median
|
26
27
|
].each do |method_name|
|
27
28
|
define_singleton_method method_name do |name|
|
28
29
|
__ensure_timer(name)
|
@@ -30,6 +31,11 @@ module TimeUp
|
|
30
31
|
end
|
31
32
|
end
|
32
33
|
|
34
|
+
def self.percentile(name, percentage)
|
35
|
+
__ensure_timer(name)
|
36
|
+
__timers[name].percentile(percentage)
|
37
|
+
end
|
38
|
+
|
33
39
|
# Interrogative methods
|
34
40
|
def self.total_elapsed
|
35
41
|
__timers.values.sum(&:elapsed)
|
@@ -41,6 +47,10 @@ module TimeUp
|
|
41
47
|
}.to_h
|
42
48
|
end
|
43
49
|
|
50
|
+
def self.all_timers
|
51
|
+
__timers.values
|
52
|
+
end
|
53
|
+
|
44
54
|
def self.all_stats
|
45
55
|
__timers.values.map { |timer|
|
46
56
|
[timer.name, {
|
@@ -48,7 +58,9 @@ module TimeUp
|
|
48
58
|
count: timer.count,
|
49
59
|
min: timer.min,
|
50
60
|
max: timer.max,
|
51
|
-
mean: timer.mean
|
61
|
+
mean: timer.mean,
|
62
|
+
median: timer.median,
|
63
|
+
"95th": timer.percentile(95)
|
52
64
|
}]
|
53
65
|
}.to_h
|
54
66
|
end
|
@@ -65,7 +77,7 @@ module TimeUp
|
|
65
77
|
}
|
66
78
|
io.puts <<~SUMMARY
|
67
79
|
|
68
|
-
TimeUp
|
80
|
+
TimeUp summary
|
69
81
|
========================
|
70
82
|
#{summaries.join("\n")}
|
71
83
|
|
@@ -73,6 +85,56 @@ module TimeUp
|
|
73
85
|
SUMMARY
|
74
86
|
end
|
75
87
|
|
88
|
+
def self.print_detailed_summary(io = $stdout)
|
89
|
+
cols = {
|
90
|
+
names: ["Name"],
|
91
|
+
elapsed: ["Elapsed"],
|
92
|
+
count: ["Count"],
|
93
|
+
min: ["Min"],
|
94
|
+
max: ["Max"],
|
95
|
+
mean: ["Mean"],
|
96
|
+
median: ["Median"],
|
97
|
+
"95th": ["95th %"]
|
98
|
+
}
|
99
|
+
__timers.values.each { |timer|
|
100
|
+
cols[:names] << "#{timer.name.inspect}#{"*" if timer.active?}"
|
101
|
+
cols[:elapsed] << "%.5f" % timer.elapsed
|
102
|
+
cols[:count] << timer.count.to_s
|
103
|
+
cols[:min] << "%.5f" % timer.min
|
104
|
+
cols[:max] << "%.5f" % timer.max
|
105
|
+
cols[:mean] << "%.5f" % timer.mean
|
106
|
+
cols[:median] << "%.5f" % timer.median
|
107
|
+
cols[:"95th"] << "%.5f" % timer.percentile(95)
|
108
|
+
}
|
109
|
+
|
110
|
+
widths = cols.map { |name, vals|
|
111
|
+
[name, vals.map(&:length).max]
|
112
|
+
}.to_h
|
113
|
+
|
114
|
+
rows = cols[:names].size.times.map { |i|
|
115
|
+
if i == 0
|
116
|
+
cols.keys.map { |name|
|
117
|
+
cols[name][i].center(widths[name])
|
118
|
+
}
|
119
|
+
else
|
120
|
+
cols.keys.map { |name|
|
121
|
+
cols[name][i].ljust(widths[name])
|
122
|
+
}
|
123
|
+
end
|
124
|
+
}
|
125
|
+
|
126
|
+
full_width = widths.values.sum + (rows[0].size - 1) * 3
|
127
|
+
io.puts <<~SUMMARY
|
128
|
+
|
129
|
+
#{"=" * full_width}
|
130
|
+
#{rows[0].join(" | ")}
|
131
|
+
#{"-" * full_width}
|
132
|
+
#{rows[1..-1].map { |row| row.join(" | ") }.join("\n")}
|
133
|
+
|
134
|
+
#{"* Denotes that the timer is still active\n" if __timers.values.any?(&:active?)}
|
135
|
+
SUMMARY
|
136
|
+
end
|
137
|
+
|
76
138
|
# Iterative methods
|
77
139
|
def self.stop_all
|
78
140
|
__timers.values.each(&:stop)
|
@@ -89,7 +151,7 @@ module TimeUp
|
|
89
151
|
|
90
152
|
# Internal methods
|
91
153
|
def self.__timers
|
92
|
-
Thread.current[:time_up_timers]
|
154
|
+
Thread.current[:time_up_timers] ||= {}
|
93
155
|
end
|
94
156
|
|
95
157
|
def self.__ensure_timer(name)
|
@@ -165,6 +227,25 @@ module TimeUp
|
|
165
227
|
times.sum / times.size
|
166
228
|
end
|
167
229
|
|
230
|
+
def median
|
231
|
+
times = timings.sort
|
232
|
+
return if times.empty?
|
233
|
+
(times[(times.size - 1) / 2] + times[times.size / 2]) / 2.0
|
234
|
+
end
|
235
|
+
|
236
|
+
def percentile(percent)
|
237
|
+
times = timings.sort
|
238
|
+
return if times.empty?
|
239
|
+
return 0 if percent <= 0
|
240
|
+
return max if percent >= 100
|
241
|
+
return times.first if times.size == 1
|
242
|
+
position = (percent / 100.0) * (times.size - 1)
|
243
|
+
|
244
|
+
partial_ratio = position - position.floor
|
245
|
+
whole, partial = times[position.floor, 2]
|
246
|
+
whole + (partial - whole) * partial_ratio
|
247
|
+
end
|
248
|
+
|
168
249
|
def timings
|
169
250
|
if active?
|
170
251
|
@past_timings + [now - @start_time]
|
data/lib/time_up/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: time_up
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Justin Searls
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-07-
|
11
|
+
date: 2021-07-24 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email:
|
@@ -19,6 +19,7 @@ extra_rdoc_files: []
|
|
19
19
|
files:
|
20
20
|
- ".github/workflows/main.yml"
|
21
21
|
- ".gitignore"
|
22
|
+
- ".standard.yml"
|
22
23
|
- CHANGELOG.md
|
23
24
|
- Gemfile
|
24
25
|
- Gemfile.lock
|