Class: Philiprehberger::Stopwatch
- Inherits:
-
Object
- Object
- Philiprehberger::Stopwatch
- Defined in:
- lib/philiprehberger/stopwatch.rb,
lib/philiprehberger/stopwatch/version.rb
Defined Under Namespace
Classes: Error
Constant Summary collapse
- VERSION =
'0.5.0'
Class Method Summary collapse
-
.format_duration(seconds) ⇒ String
Format a duration in seconds as a human-readable string.
-
.measure { ... } ⇒ Array
Measure execution time of a block.
-
.measure_formatted { ... } ⇒ String
Measure execution time and return formatted string.
Instance Method Summary collapse
-
#checkpoint(name) ⇒ self
Record a named checkpoint at the current cumulative elapsed time.
-
#checkpoints ⇒ Hash
Return a copy of all recorded checkpoints.
-
#elapsed ⇒ Float
Get total elapsed time in seconds.
-
#elapsed_at(name) ⇒ Float
Return the cumulative elapsed time recorded at a named checkpoint.
-
#elapsed_ms ⇒ Float
Get total elapsed time in milliseconds.
-
#elapsed_us ⇒ Float
Get total elapsed time in microseconds.
-
#formatted_elapsed ⇒ String
Format elapsed time as a human-readable string.
-
#formatted_laps ⇒ Array<Hash>
Get formatted lap data.
-
#initialize ⇒ Stopwatch
constructor
A new instance of Stopwatch.
-
#lap(name = nil) ⇒ Hash
Record a lap.
-
#lap_stats ⇒ Hash
Get aggregate statistics across all recorded laps.
-
#laps ⇒ Array<Hash>
Get all recorded laps.
-
#paused? ⇒ Boolean
Check if the stopwatch is paused.
-
#reset ⇒ self
Reset the stopwatch.
-
#restart ⇒ self
Reset and start the stopwatch in one call.
-
#running? ⇒ Boolean
Check if the stopwatch is running (and not paused).
-
#since(name) ⇒ Float
Return the elapsed time since a named checkpoint was recorded.
-
#start ⇒ self
(also: #resume)
Start the stopwatch.
-
#stop ⇒ self
(also: #pause)
Stop (pause) the stopwatch.
-
#to_h ⇒ Hash
Serialize the stopwatch state to a hash.
Constructor Details
#initialize ⇒ Stopwatch
Returns a new instance of Stopwatch.
9 10 11 12 13 14 15 16 17 |
# File 'lib/philiprehberger/stopwatch.rb', line 9 def initialize @laps = [] @checkpoints = {} @running = false @paused = false @start_time = nil @elapsed_before_pause = 0.0 @lap_start = nil end |
Class Method Details
.format_duration(seconds) ⇒ String
Format a duration in seconds as a human-readable string
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 |
# File 'lib/philiprehberger/stopwatch.rb', line 255 def self.format_duration(seconds) if seconds < 0.001 format('%.2fus', seconds * 1_000_000) elsif seconds < 1.0 format('%.2fms', seconds * 1_000) elsif seconds < 60.0 format('%.3fs', seconds) elsif seconds < 3600.0 minutes = (seconds / 60).to_i secs = (seconds % 60).to_i "#{minutes}m #{secs}s" else hours = (seconds / 3600).to_i minutes = ((seconds % 3600) / 60).to_i secs = (seconds % 60).to_i "#{hours}h #{minutes}m #{secs}s" end end |
.measure { ... } ⇒ Array
Measure execution time of a block
235 236 237 238 239 240 |
# File 'lib/philiprehberger/stopwatch.rb', line 235 def self.measure start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC) result = yield elapsed = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start_time [result, elapsed] end |
.measure_formatted { ... } ⇒ String
Measure execution time and return formatted string
246 247 248 249 |
# File 'lib/philiprehberger/stopwatch.rb', line 246 def self.measure_formatted(&) _, elapsed = measure(&) format_duration(elapsed) end |
Instance Method Details
#checkpoint(name) ⇒ self
Record a named checkpoint at the current cumulative elapsed time
126 127 128 129 130 131 132 133 |
# File 'lib/philiprehberger/stopwatch.rb', line 126 def checkpoint(name) raise Error, 'stopwatch is not running' unless @running current = now split = @elapsed_before_pause + (current - @start_time) @checkpoints[name] = split self end |
#checkpoints ⇒ Hash
Return a copy of all recorded checkpoints
158 159 160 |
# File 'lib/philiprehberger/stopwatch.rb', line 158 def checkpoints @checkpoints.dup end |
#elapsed ⇒ Float
Get total elapsed time in seconds
107 108 109 110 111 112 113 |
# File 'lib/philiprehberger/stopwatch.rb', line 107 def elapsed if @running && !@paused @elapsed_before_pause + (now - @start_time) else @elapsed_before_pause end end |
#elapsed_at(name) ⇒ Float
Return the cumulative elapsed time recorded at a named checkpoint
139 140 141 142 143 |
# File 'lib/philiprehberger/stopwatch.rb', line 139 def elapsed_at(name) raise Error, "checkpoint '#{name}' not found" unless @checkpoints.key?(name) @checkpoints[name] end |
#elapsed_ms ⇒ Float
Get total elapsed time in milliseconds
93 94 95 |
# File 'lib/philiprehberger/stopwatch.rb', line 93 def elapsed_ms elapsed * 1000.0 end |
#elapsed_us ⇒ Float
Get total elapsed time in microseconds
100 101 102 |
# File 'lib/philiprehberger/stopwatch.rb', line 100 def elapsed_us elapsed * 1_000_000.0 end |
#formatted_elapsed ⇒ String
Format elapsed time as a human-readable string
184 185 186 |
# File 'lib/philiprehberger/stopwatch.rb', line 184 def formatted_elapsed self.class.format_duration(elapsed) end |
#formatted_laps ⇒ Array<Hash>
Get formatted lap data
191 192 193 194 195 196 197 198 199 200 201 |
# File 'lib/philiprehberger/stopwatch.rb', line 191 def formatted_laps @laps.map do |lap| { name: lap[:name], elapsed: lap[:elapsed], split: lap[:split], formatted: self.class.format_duration(lap[:elapsed]), formatted_split: self.class.format_duration(lap[:split]) } end end |
#lap(name = nil) ⇒ Hash
Record a lap
78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/philiprehberger/stopwatch.rb', line 78 def lap(name = nil) raise Error, 'stopwatch is not running' unless @running current = now lap_elapsed = current - @lap_start split = @elapsed_before_pause + (current - @start_time) lap_data = { name: name, elapsed: lap_elapsed, split: split } @laps << lap_data @lap_start = current lap_data end |
#lap_stats ⇒ Hash
Get aggregate statistics across all recorded laps
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/philiprehberger/stopwatch.rb', line 165 def lap_stats if @laps.empty? return { count: 0, total: 0.0, avg: 0.0, min: 0.0, max: 0.0 } end times = @laps.map { |l| l[:elapsed] } total = times.sum { count: times.length, total: total, avg: total / times.length, min: times.min, max: times.max } end |
#laps ⇒ Array<Hash>
Get all recorded laps
118 119 120 |
# File 'lib/philiprehberger/stopwatch.rb', line 118 def laps @laps.dup end |
#paused? ⇒ Boolean
Check if the stopwatch is paused
220 221 222 |
# File 'lib/philiprehberger/stopwatch.rb', line 220 def paused? @paused end |
#reset ⇒ self
Reset the stopwatch
52 53 54 55 56 57 58 59 60 61 |
# File 'lib/philiprehberger/stopwatch.rb', line 52 def reset @laps = [] @checkpoints = {} @running = false @paused = false @start_time = nil @elapsed_before_pause = 0.0 @lap_start = nil self end |
#restart ⇒ self
Reset and start the stopwatch in one call
66 67 68 69 |
# File 'lib/philiprehberger/stopwatch.rb', line 66 def restart reset start end |
#running? ⇒ Boolean
Check if the stopwatch is running (and not paused)
227 228 229 |
# File 'lib/philiprehberger/stopwatch.rb', line 227 def running? @running && !@paused end |
#since(name) ⇒ Float
Return the elapsed time since a named checkpoint was recorded
149 150 151 152 153 |
# File 'lib/philiprehberger/stopwatch.rb', line 149 def since(name) raise Error, "checkpoint '#{name}' not found" unless @checkpoints.key?(name) elapsed - @checkpoints[name] end |
#start ⇒ self Also known as: resume
Start the stopwatch
22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
# File 'lib/philiprehberger/stopwatch.rb', line 22 def start raise Error, 'stopwatch is already running' if @running && !@paused @start_time = now if @paused @paused = false else @elapsed_before_pause = 0.0 @lap_start = @start_time @laps = [] end @running = true self end |
#stop ⇒ self Also known as: pause
Stop (pause) the stopwatch
40 41 42 43 44 45 46 47 |
# File 'lib/philiprehberger/stopwatch.rb', line 40 def stop raise Error, 'stopwatch is not running' unless @running raise Error, 'stopwatch is already paused' if @paused @elapsed_before_pause += now - @start_time @paused = true self end |
#to_h ⇒ Hash
Serialize the stopwatch state to a hash
206 207 208 209 210 211 212 213 214 215 |
# File 'lib/philiprehberger/stopwatch.rb', line 206 def to_h { running: running?, paused: paused?, elapsed: elapsed, formatted_elapsed: formatted_elapsed, laps: laps, lap_stats: lap_stats } end |