| 46 | |
| 47 | |
| 48 | def timeit(fn, reset=None): |
| 49 | # `reset` (if given) runs UNTIMED before each iteration — used to clear |
| 50 | # SymPy's global cache so every timed iteration does real work from source, |
| 51 | # consistent with how the other tools rebuild from source each call. |
| 52 | if reset: |
| 53 | reset() |
| 54 | t = time.perf_counter() |
| 55 | fn() |
| 56 | first = (time.perf_counter() - t) * 1000 |
| 57 | iterations = min(50, max(1, round(150 / max(first, 0.01)))) |
| 58 | for _ in range(min(3, iterations)): |
| 59 | if reset: |
| 60 | reset() |
| 61 | fn() |
| 62 | times = [] |
| 63 | for _ in range(iterations): |
| 64 | if reset: |
| 65 | reset() |
| 66 | t = time.perf_counter() |
| 67 | fn() |
| 68 | times.append((time.perf_counter() - t) * 1000) |
| 69 | return {"timeMs": median(times), "minMs": min(times), "iterations": iterations} |
| 70 | |
| 71 | |
| 72 | # --------------------------------------------------------------------------- # |