Precision stopwatch with lap timing, pause/resume, and formatted output
gem install philiprehberger-stopwatchPrecision stopwatch with lap timing, pause/resume, and formatted output
Add to your Gemfile:
gem "philiprehberger-stopwatch"
Or install directly:
gem install philiprehberger-stopwatch
require "philiprehberger/stopwatch"
sw = Philiprehberger::Stopwatch.new
sw.start
# ... do work ...
sw.lap('phase 1')
# ... do more work ...
sw.lap('phase 2')
sw.stop
sw.elapsed # => 1.234 (seconds)
sw.laps # => [{name: "phase 1", elapsed: 0.5, split: 0.5}, {name: "phase 2", elapsed: 0.734, split: 1.234}]
sw = Philiprehberger::Stopwatch.new
sw.start
sleep(0.1)
sw.pause # alias for #stop
sw.resume # alias for #start
sleep(0.1)
sw.stop
sw.elapsed # => ~0.2 (paused time not counted)
sw = Philiprehberger::Stopwatch.new
sw.start
sleep(0.1)
sw.lap('phase 1')
sw.restart # equivalent to #reset followed by #start
sleep(0.05)
sw.elapsed # => ~0.05 (prior state cleared)
sw = Philiprehberger::Stopwatch.new
sw.start
sleep(0.5)
sw.formatted_elapsed # => "500.12ms"
sleep(65)
sw.formatted_elapsed # => "1m 5s"
sw = Philiprehberger::Stopwatch.new
sw.start
sw.lap('setup')
sw.lap('process')
sw.lap('teardown')
sw.lap_stats
# => { count: 3, total: 0.053, avg: 0.018, min: 0.005, max: 0.031 }
sw.formatted_laps
# => [{ name: "setup", elapsed: 0.005, formatted: "5.00ms" }, ...]
sw = Philiprehberger::Stopwatch.new
sw.start
sw.lap('setup')
sw.lap('process')
sw.stop
sw.to_h
# => { running: false, paused: true, elapsed: 0.053,
# formatted_elapsed: "53.00ms", laps: [...], lap_stats: {...} }
sw = Philiprehberger::Stopwatch.new
sw.start
sleep(0.1)
sw.checkpoint('after_setup')
sleep(0.2)
sw.checkpoint('after_process')
sw.elapsed_at('after_setup') # => ~0.1 (cumulative split at that moment)
sw.elapsed_at('after_process') # => ~0.3
sw.since('after_setup') # => ~0.2 (time elapsed since that checkpoint)
sw.since('after_process') # => ~0.0
sw.checkpoints
# => { "after_setup" => 0.1003, "after_process" => 0.3007 }
result, elapsed = Philiprehberger::Stopwatch.measure { expensive_operation }
puts "Took #{elapsed} seconds"
formatted = Philiprehberger::Stopwatch.measure_formatted { expensive_operation }
puts "Took #{formatted}" # => "Took 12.50ms"
For ad-hoc per-iteration timing in loops where naming each lap is overkill:
sw = Philiprehberger::Stopwatch.new.start
items.each do |item|
process(item)
puts "step took #{sw.tick} seconds"
end
Each call to #tick returns the seconds elapsed since the previous tick
(or since #start for the first call). A thinner #lap for unnamed
sequential measurement.
| Method | Description |
|---|---|
Stopwatch.new | Create a new stopwatch |
#start | Start or resume the stopwatch |
#stop | Pause the stopwatch |
#pause | Alias for #stop |
#resume | Alias for #start (resumes a paused stopwatch) |
#reset | Reset all state |
#restart | Reset and start the stopwatch in one call |
#lap(name) | Record a lap with optional name |
#tick | Return seconds since the previous tick (or since start on the first call) |
#elapsed | Total elapsed time in seconds |
#elapsed_ms | Total elapsed time in milliseconds |
#elapsed_us | Total elapsed time in microseconds |
#laps | Array of recorded lap data |
#running? | Whether the stopwatch is actively running |
#paused? | Whether the stopwatch is paused |
#checkpoint(name) | Record a named moment storing the current cumulative split time |
#elapsed_at(name) | Cumulative split time at the named checkpoint |
#since(name) | Elapsed time since the named checkpoint was recorded |
#checkpoints | Hash of all recorded checkpoints |
#lap_stats | Aggregate lap statistics (count, total, avg, min, max) |
#formatted_elapsed | Human-readable elapsed time string |
#formatted_laps | Array of laps with formatted times |
#to_h | Serialize full stopwatch state to a hash |
Stopwatch.measure { block } | Measure block execution time |
Stopwatch.measure_formatted { block } | Measure block and return formatted string |
bundle install
bundle exec rspec
bundle exec rubocop
If you find this project useful: