https://github.com/somombo/time-it
Lean 4 execution timer built to allow blackbox testing and programmatic inspection of elapsed time
https://github.com/somombo/time-it
benchmarking blackbox lean lean4 monad performance profiling timer timing
Last synced: 10 days ago
JSON representation
Lean 4 execution timer built to allow blackbox testing and programmatic inspection of elapsed time
- Host: GitHub
- URL: https://github.com/somombo/time-it
- Owner: somombo
- License: apache-2.0
- Created: 2026-06-04T22:25:53.000Z (24 days ago)
- Default Branch: main
- Last Pushed: 2026-06-04T22:53:34.000Z (24 days ago)
- Last Synced: 2026-06-05T00:11:59.543Z (24 days ago)
- Topics: benchmarking, blackbox, lean, lean4, monad, performance, profiling, timer, timing
- Language: Lean
- Homepage:
- Size: 8.79 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# time-it
A monadic timing library for Lean 4.
[](https://github.com/somombo/time-it/actions/workflows/lean_action_ci.yml)
## Motivation: Shortcomings of `IO.timeit`
In Lean 4's core library, `IO.timeit` has the following signature:
```lean
def timeit (msg : String) (act : IO α) : IO α
```
While useful for quick debugging, it has significant limitations for building robust tools, testing performance regressions, or implementing custom profiling:
1. **No Programmatic Access:** `IO.timeit` prints the execution duration directly to `stderr` (using `IO.eprintln`) and only returns the result `α`. This makes it impossible to inspect, log, assert against, or store the timing data programmatically.
2. **Side Effects by Default:** It forces stdout/stderr printing, which might be undesirable in silent or structured CLI environments.
3. **Rigid Formatting:** The output format is fixed by the Lean core library and cannot be easily customized or parsed.
### The `time-it` Solution
This library provides `IO.timeAx` and `IO.timeFn`. They return the timed action's result along with the elapsed duration represented as a structured `Std.Time.Duration`:
```lean
def timeAx (ax : IO α) : IO (Duration × α)
def timeFn (f : α → β) (x : α) : IO (Duration × β)
```
Furthermore, `time-it` utilizes a `blackBox` wrapper to prevent Lean compiler optimizations (such as dead code elimination, expression hoisting, or subexpression elimination) from optimizing away or restructuring the timed operations.
---
## Installation
Add `time-it` as a dependency in your `lakefile.toml`:
```toml
[[require]]
name = "time-it"
git = "https://github.com/somombo/time-it.git"
rev = "main"
```
Then run `lake update` to fetch the dependency.
---
## Usage
### Timing an `IO` Action (`IO.timeAx`)
To measure how long an arbitrary `IO` computation takes:
```lean
import TimeIt
def performComputation : IO Unit := do
let (duration, _) ← IO.timeAx (IO.sleep 1000) -- Sleep for 1000ms
IO.println s!"The computation took {duration.toNanoseconds} ns"
```
### Timing a Function Evaluation (`IO.timeFn`)
To measure how long a function takes to evaluate on a given input:
```lean
import TimeIt
def main : IO Unit := do
let heavyComputation := fun n => (List.range n).foldl (· + ·) 0
let (duration, result) ← IO.timeFn heavyComputation 1000000
IO.println s!"Result: {result}"
IO.println s!"Calculation took: {duration.toNanoseconds} ns"
```
---
## Development & Tests
To compile and verify the library locally:
```bash
# Build the library
lake build
# Run the test suite
lake test
```