Bug 13724 – std.datetime.timeIt

Status
NEW
Severity
enhancement
Priority
P4
Component
phobos
Product
D
Version
D2
Platform
x86
OS
Windows
Creation time
2014-11-13T00:01:52Z
Last change time
2024-12-01T16:22:54Z
Keywords
bootcamp
Assigned to
No Owner
Creator
bearophile_hugs
Moved to GitHub: phobos#10097 →

Comments

Comment #0 by bearophile_hugs — 2014-11-13T00:01:52Z
I suggest to add to Phobos a very simple function like this timeIt: import std.stdio, std.datetime, std.typecons; ulong fibonacci(uint n) { if (n == 0 || n == 1) return 1; else return fibonacci(n - 1) + fibonacci(n - 2); } auto timeIt(Callable)(lazy Callable f) { StopWatch sw; sw.start; auto result = f(); sw.stop; return tuple(result, sw.peek.nsecs / 1_000_000_000.0); } void main() { 37.fibonacci.timeIt.writeln; } Output (the second item of the tuple is always in seconds): Tuple!(ulong, double)(39088169, 2.38505) The point of this function is to have something very quick and easy to use (so no configuration arguments, and nothing complex to remember) to time a function while you write code. For more refined performance testing other things should be used. This function is useful because it has a minimal cognitive burden and minimal code to be used. It's very similar to the Timing function of Mathematica, that is used often: http://reference.wolfram.com/language/ref/Timing.html
Comment #1 by schveiguy — 2014-11-13T13:36:30Z
Don't we have a std.benchmark that does something like this? BTW, I would recommend instead of returning the time in a tuple, put it in a ref parameter. This way, you can simply wrap any calls that you normally use.
Comment #2 by bearophile_hugs — 2014-11-13T14:03:10Z
(In reply to Steven Schveighoffer from comment #1) > Don't we have a std.benchmark that does something like this? Yes, but timeIt needs to be simpler. So it's a different purpose. > BTW, I would recommend instead of returning the time in a tuple, put it in a > ref parameter. This way, you can simply wrap any calls that you normally use. I don't understand. Generally I don't like ref arguments, they don't allow me simple usages as: 37.fibonacci.timeIt.writeln; 37.fibonacci.timeIt[1].writeln; Usually ref parameters require more code, and more cognitive burden. Tuples are usually winners over most alternatives.
Comment #3 by schveiguy — 2014-11-13T14:21:25Z
You're looking at it from the perspective that the time is the main thing you care about, i.e. you don't care about the return value, just the time it took. I look at it from the perspective that you want to time something that you are already using. For example, if you have something like: 37.fibonacci.foo(); Now, you want to keep your code the same, but get the time it took to do fibonacci, how do you do that with the tuple return? With a ref parameter, you can do: ulong timer; 37.fibonacci.timeIt(timer).foo(); Now I have the timer, and I don't have to mess with my call chain (much). It also allows easier cumulative timing.
Comment #4 by bearophile_hugs — 2014-11-13T14:53:04Z
(In reply to Steven Schveighoffer from comment #3) > You're looking at it from the perspective that the time is the main thing > you care about, i.e. you don't care about the return value, just the time it > took. If I want only the timing I return only the timing. But both this timeIt and the Mathematica function return a pair of the result and the time to compute it, because that's the most useful result and it's simple to handle and remember. If you take an hour to compute something you don't want to repeat the computation two times to have both result and timing. > I look at it from the perspective that you want to time something that > you are already using. > > For example, if you have something like: > > 37.fibonacci.foo(); > > Now, you want to keep your code the same, but get the time it took to do > fibonacci, how do you do that with the tuple return? > > With a ref parameter, you can do: > > ulong timer; > 37.fibonacci.timeIt(timer).foo(); > > Now I have the timer, and I don't have to mess with my call chain (much). > > It also allows easier cumulative timing. This is a different and more complex usage. It's interesting, but fails at being very simple and short. So I am not sure. Also "timer" in your example is an not-precisely typed variable (raw typed) (and it's not a double). > how do you do that with the tuple return? In a functional language you often have "glue" that allows you to solve such simple problems in a standard and simple way.
Comment #5 by schveiguy — 2014-11-13T15:03:17Z
(In reply to bearophile_hugs from comment #4) > (In reply to Steven Schveighoffer from comment #3) > > You're looking at it from the perspective that the time is the main thing > > you care about, i.e. you don't care about the return value, just the time it > > took. > > If I want only the timing I return only the timing. But both this timeIt and > the Mathematica function return a pair of the result and the time to compute > it, because that's the most useful result and it's simple to handle and > remember. If you take an hour to compute something you don't want to repeat > the computation two times to have both result and timing. Mathematica is not D :) I was never saying to repeat the function, so I'm not sure where that came from. > > I look at it from the perspective that you want to time something that > > you are already using. > > > > For example, if you have something like: > > > > 37.fibonacci.foo(); > > > > Now, you want to keep your code the same, but get the time it took to do > > fibonacci, how do you do that with the tuple return? > > > > With a ref parameter, you can do: > > > > ulong timer; > > 37.fibonacci.timeIt(timer).foo(); > > > > Now I have the timer, and I don't have to mess with my call chain (much). > > > > It also allows easier cumulative timing. > > This is a different and more complex usage. It's interesting, but fails at > being very simple and short. So I am not sure. I don't know if you have considered the usage if you wanted to use your method: auto x = 37.fibonacci.timeIt; foo(x[0]); Maybe as short as mine, but not simple. This breaks up your chain. If you were timing multiple things in the chain, you have to break it wherever timeIt is inserted. If you wanted cumulative time, you have to take the extra step of adding them all together. > > Also "timer" in your example is an not-precisely typed variable (raw typed) > (and it's not a double). Sure, make it a double then :) I would recommend actually making it a Duration. > > how do you do that with the tuple return? > > In a functional language you often have "glue" that allows you to solve such > simple problems in a standard and simple way. Somehow you have to say "do this with the first part of the tuple, do that with the second part". I don't think it's very straightforward. In D, if you want to deal with the tuple in parts, you have to separate the statements, or start throwing in some helper delegates. It doesn't sound appealing to me.
Comment #6 by bearophile_hugs — 2014-12-17T10:07:55Z
What about supporting both kinds of use (if you don't give an argument it returns the timing): 37.fibonacci.timeIt.writeln; Duration t; 37.fibonacci.timeIt(t).foo();
Comment #7 by jack — 2016-04-05T00:24:41Z
Doesn't std.datetime.benchmark handle this?
Comment #8 by schveiguy — 2016-04-05T15:24:07Z
(In reply to Jack Stouffer from comment #7) > Doesn't std.datetime.benchmark handle this? See above discussion :)
Comment #9 by issues.dlang — 2018-04-01T00:36:00Z
I'm not at all convinced that this is worth adding, but if I were to add something like this, I would probably make it use a callback that gave the Duration so that it would be simple to do something like turn auto foo = doSomething(args); into auto foo = timeIt!(a => writefln("doSomething: %s, a))(doSomething(args)); or void printIt(Duration d, string file = __FILE__, size_t line = __LINE__) { writefln("%s(%s): %s", file, line, d); } auto foo = timeIt!printIt(doSomething(args)); But then again, the only reason I see to have a function like this would be to do something like print or log the results of a particular run. It certainly isn't appropriate for benchmarking.
Comment #10 by robert.schadek — 2024-12-01T16:22:54Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/phobos/issues/10097 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB