Ever need to measure the elapsed wall-time for one or more bits of Ruby code,
but don't necessarily want to reach for
Benchmark or roll your own ad hoc measurement code?
Try time_up
!
This gem is especially useful for long-running processes (like test suites) that have several time-intensive operations that are repeated over the life of the process and that you want to measure in aggregate. (For example, to see how much time your test suite spends creating factories, truncating the database, or invoking a critical code path.)
Here's a blog post about time_up and a great example of when it can be useful.
Just run gem install time_up
or add time_up to your Gemfile:
gem "time_up"
Starting a timer is easy! Just call TimeUp.start
:
# Pass a block and time_up will only count the time while the block executes:
TimeUp.start(:factories) do
# … create some factories
end
# Without a block, a started timer will run until you stop it:
TimeUp.start(:truncation)
# … truncate some stuff
TimeUp.stop(:truncation)
To get the total time that's elapsed while the timer has been running, call
elapsed
:
slow_time = TimeUp.elapsed(:slow_code_path)
Which will return a Float
representing the number of seconds that have elapsed
while the timer is running.
Timers aggregate total elapsed time running, just like a digital stopwatch. That means if you start a timer after it's been stopped, the additional time will be added to the previous elapsed time:
TimeUp.start :eggs
sleep 1
puts TimeUp.stop :eggs # => ~1.0
TimeUp.start :eggs
sleep 1
# To get the elapsed time without necessarily stopping the timer, call `elapsed`
puts TimeUp.elapsed :eggs # => ~2.0
# To reset a timer to 0, call `reset` (if it's running, it'll keep running!)
TimeUp.reset :eggs
sleep 5
puts TimeUp.stop :eggs # => ~5.0
When passes without a block, TimeUp.start
returns an instance of the timer,
which has its own start
, stop
, elaped
, and reset
methods. If you want to
find that instance later, you can also call TimeUp.timer(:some_name)
. So the
above example could be rewritten as:
egg_timer = TimeUp.start :eggs
sleep 1
puts egg_timer.stop # => ~1.0
egg_timer.start
sleep 1
# To get the elapsed time without necessarily stopping the timer, call `elapsed`
puts egg_timer.elapsed # => ~2.0
# To reset a timer to 0, call `reset` (if it's running, it'll keep running!)
egg_timer.reset
sleep 5
puts egg_timer.stop # => ~5.0
Finally, if you're juggling a bunch of timers, you can get a summary report of them printed for you, like so:
TimeUp.start :roast
sleep 0.03
TimeUp.start :veggies
sleep 0.02
TimeUp.start :pasta
sleep 0.01
TimeUp.stop_all
TimeUp.start :souffle
TimeUp.print_summary
Which will output something like:
TimeUp summary
========================
:roast 0.07267s
:veggies 0.03760s
:pasta 0.01257s
:souffle* 0.00003s
* Denotes that the timer is still active
And if you're calling the timers multiple times and want to see some basic
statistics in the print-out, you can call TimeUp.print_detailed_summary
, which
will produce this:
=============================================================================
Name | Elapsed | Count | Min | Max | Mean | Median | 95th %
-----------------------------------------------------------------------------
:roast | 0.08454 | 3 | 0.00128 | 0.07280 | 0.02818 | 0.01046 | 0.06657
:veggies | 0.03779 | 1 | 0.03779 | 0.03779 | 0.03779 | 0.03779 | 0.03779
:pasta | 0.01260 | 11 | 0.00000 | 0.01258 | 0.00115 | 0.00000 | 0.00630
:souffle* | 0.00024 | 1 | 0.00024 | 0.00025 | 0.00025 | 0.00025 | 0.00026
* Denotes that the timer is still active
This gem defines a bunch of public methods but they're all pretty short and straightforward, so when in doubt, I'd encourage you to read the code.
TimeUp.timer(name)
- Returns the Timer
instance named name
(creating it,
if it doesn't exist)
TimeUp.start(name, [&blk])
- Starts (or restarts) a named
Timer. If passed a block, will return whatever the block
evaluates to. If called without a block, it will return the timer object
TimeUp.stop(name)
- Stops the named timer
TimeUp.reset(name)
- Resets the named timer's elapsed time to 0, effectively
restarting it if it's currently running
TimeUp.elapsed(name)
- Returns a Float
of the total elapsed seconds that the
named timer has been running
TimeUp.timings(name)
- Returns an array of each recorded start-to-stop
duration (including the current one, if the timer is running) of the named timer
TimeUp.count(name)
- The number of times the timer has been started (including
the current timing, if the timer is running)
TimeUp.min(name)
- The shortest recording by the timer
TimeUp.max(name)
- The longest recording by the timer
TimeUp.mean(name)
- The arithmetic mean of all recordings by the timer
TimeUp.median(name)
- The median of all recordings by the timer
TimeUp.percentile(name, percent)
- The timing for the given
percentile of all recordings by the
timer
TimeUp.total_elapsed
- Returns a Float
of the sum of elapsed
across all
the timers you've created (note that because you can easily run multiple logical
timers simultaneously, this figure may exceed the total time spent by the
computer)
TimeUp.all_elapsed
- Returns a Hash of timer name keys mapped to their
elapsed
values. Handy for grabbing a reference to a snapshot of the state of
things without requiring you to stop your timers
TimeUp.all_stats
- Returns a Hash of timer name keys mapped to another
hash of their basic statistics (elapsed
, count
, min
, max
,
and mean
)
TimeUp.active_timers
- Returns an Array of all timers that are currently
running. Useful for detecting cases where you might be keeping time in multiple
places simultaneously
TimeUp.print_summary([io])
- Pretty-prints a multi-line summary of all your
timers' total elapsed times to standard output (or the provided
IO)
TimeUp.print_detailed_summary([io])
- Pretty-prints a multi-line summary of
all your timers' elapsed times and basic statistics to standard output (or the
provided IO)
TimeUp.stop_all
- Stops all timers
TimeUp.reset_all
- Resets all timers
TimeUp.delete_all
- Stops and resets all timers and deletes any internal
reference to them
start
- Starts the timer
stop
- Stops the timer
elapsed
- A Float
of the total elapsed seconds the timer has been running
timings
- Returns an Array of each recorded start-to-stop duration of the
timer (including the current one, if the timer is running)
count
- The number of times the timer has been started and stopped
min
- The shortest recording of the timer
max
- The longest recording of the timer
mean
- The arithmetic mean of all recorded durations of the timer
median(name)
- The median of all recordings by the timer
percentile(name, percent)
- The timing for the given
percentile of all recordings by the
timer
active?
- Returns true
if the timer is running
reset(force: false)
- Resets the timer to 0 elapsed seconds. If force
is
true, will also stop the timer if it's running
This project follows Test Double's code of conduct for all community interactions, including (but not limited to) one-on-one communications, public posts/comments, code reviews, pull requests, and GitHub issues. If violations occur, Test Double will take any action they deem appropriate for the infraction, up to and including blocking a user from the organization's repositories.