I'm trying to use the Scala extensions to extend the String context to time the execution of a costly method And I came with this:
extension(sc: StringContext)
def timeit(args: Any*): String = {
val startTime = System.currentTimeMillis();
// sc.parts.evaluate??
val result = sc.s(args*) + s.parts().mkstring("");
result + " took " + (System.currentTimeMillis() - startTime) + " millisecs"
}
Unfortunately I don't see a way to intercept before the sc.parts are evaluated, so there is not much sense in measuring time. Is there a way to record the startTime before the sc.parts are evaluated? Do a call by name somehow? Or some other ways?
You need to use inline def
, but you also need to make sure that all arguments are inline
as well (so that their code would be inlined, not their result):
// code where all arguments are inlined
extension(inline sc: StringContext)
inline def timeit(inline args: Any*): String = {
val startTime = System.currentTimeMillis()
val result = sc.s(args*)
val endTime = System.currentTimeMillis()
s"$result took ${endTime - startTime} millisecs"
}
println(timeit"This string ${ { Thread.sleep(100); "is" } } taking ${ { Thread.sleep(250); "a while" } }")
// code where arguments are NOT inlined
extension(sc: StringContext)
inline def timeit2(args: Any*): String = {
val startTime = System.currentTimeMillis()
val result = sc.s(args*)
val endTime = System.currentTimeMillis()
s"$result took ${endTime - startTime} millisecs"
}
println(timeit2"This string ${ { Thread.sleep(100); "is" } } taking ${ { Thread.sleep(250); "a while" } }")
This string is taking a while took 354 millisecs
This string is taking a while took 1 millisecs