hyrule
hyrule copied to clipboard
time-it macro
As inspired by @gilch in discussion here: https://github.com/hylang/hy/pull/1179
The macro:
(defmacro/g! time-it [expr &optional setup round]
`((fn []
(do (import [timeit [timeit :as ~g!timeit]])
~(when setup setup)
(defn testee [] ~expr)
(setv kwargs {})
~(when round `(assoc kwargs "number" ~round))
(apply ~g!timeit [testee] kwargs)))))
hy 0.11.0+353.gca6fd66 using CPython(default) 3.5.2 on Linux
=> (defmacro/g! time-it [expr &optional setup round]
... `((fn []
... (do (import [timeit [timeit :as ~g!timeit]])
... ~(when setup setup)
... (defn testee [] ~expr)
... (setv kwargs {})
... ~(when round `(assoc kwargs "number" ~round))
... (apply ~g!timeit [testee] kwargs)))))
=> (time-it (inc 1))
0.6166748020004889
=> (time-it (inc anwser))
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "<input>", line 1, in _hy_anon_fn_2
File "/usr/lib64/python3.5/timeit.py", line 213, in timeit
return Timer(stmt, setup, timer, globals).timeit(number)
File "/usr/lib64/python3.5/timeit.py", line 178, in timeit
timing = self.inner(it, self.timer)
File "<timeit-src>", line 6, in inner
File "<input>", line 1, in testee
NameError: name 'anwser' is not defined
=> (time-it (inc answer) (do (print "thinking.." (setv answer 42))))
thinking.. 42
0.641465346001496
=> (time-it (inc a) (setv a 12) 100)
6.975599899305962e-05
=> (time-it (inc 1) () 100)
6.572400161530823e-05
=> (time-it (inc 1) :round 100) ;; works by accident, :round by itself is a valid expression
6.490799933089875e-05
Another approach is using read-str
Caveat
I've been fighting the macro system for the last hour, as we cannot use &kwargs
with defmacro
, so unless we use &rest
and parse the argument ourselves (I have a kind-of-working prototype, but it is so ugly that I do not dare to share), the form of the macro is a bit rigid, I skipped the timer
argument for simplicity's sake, and right now, one have to pass in the setup
code to specify the round of iteration, see above.