pocket_watch
pocket_watch is a lightweight rapid benchmarking library.
If you have a function or two that are taking longer than expected to run, you can quickly measure their execution time using this library!
Well it’s fast most of the time, but sometimes it gets really slow.
Try one of the summary functions, which collect execution times over
multiple runs and give you aggregate stats. You can even run a function
multiple times each time it’s called, and simply return the first value
collected without interrupting your normal control flow!
Cool. Can I trace the execution time of every function called in my application throughout its lifecycle, along with memory usage and cache-miss rates?
Whoa there buckaroo– this is a pocket watch, not a profiler!
If you need more control, more precision, or a deeper integration into your runtime, I suggest looking into Erlang– or JavaScript-specific profiling tools.
gleam add pocket_watch@2
Examples
Simple:
import pocket_watch
pub fn main() {
use <- pocket_watch.simple("with `use`")
a_long()
|> long
|> very_slow
|> pipeline
}
// pocket_watch [with `use`]: took 42.0s
Without use:
import pocket_watch
pub fn main() {
let fun = fn() { a_slow_function("with", "arguments") }
pocket_watch.simple("without `use`", fun)
}
// pocket_watch [without `use`]: took 800ms
With a custom callback:
import simplifile
import pocket_watch
fn log_time(label, elapsed) {
simplifile.append(
to: "./log.txt",
contents: label <> ": took " <> elapsed <> "\n",
)
}
pub fn main() {
use <- pocket_watch.callback(log_time("logged function", _))
another_very()
slow_block_of_code()
}
// in ./log.txt:
// logged function: took 6.9m
Run a function multiple times and aggregate the results:
import pocket_watch
pub fn main() {
use <- pocket_watch.summary_simple("simple summary", runs: 100, warmup: 0)
function_thats_usually_fast_but_occasionally_really_slow()
}
// pocket_watch [simple summary]: min: 210.0ns, max: 100.02ms, median: 6.0ms, mean: 12.77ms
// warmup: 0/0.0ns, total post-warmup: 100/1.28s
Aggregate with a custom callback:
import pocket_watch/summary
pub fn main() {
use <- summary.callback(
runs: 10_000,
warmup: 100,
with: summary.label("sprint", summary.show_rates),
)
function_that_gets_faster_over_time()
}
// pocket_watch [sprint]: warmup: 6.6/s, post-warmup: 13.63/s
Collect a summary to work with directly:
import pocket_watch/summary.{Summary}
pub fn main() {
let Summary(
values:, // List of return values from each run
times:, // List of times from each run
runs:, // Number of runs
warmup_runs:, // Number of warmup runs
warmup:, // Warmup time elapsed
total:, // Total (post-warmup) time elapsed
min:, // Fastest run time
max:, // Slowest run time
median:, // Median run time
mean:, // Mean/average run time
) = summary.collect(runs: 100, warmup: 0, time: yet_another_function)
}
Further documentation can be found at https://hexdocs.pm/pocket_watch.
Development
gleam run # Run the project
gleam test # Run the tests