Boost logo

Boost :

Subject: Re: [boost] [Chrono] Proposed library now feature complete
From: Howard Hinnant (hinnant_at_[hidden])
Date: 2008-11-18 21:49:29


On Nov 18, 2008, at 5:28 PM, Beman Dawes wrote:

> On Tue, Nov 18, 2008 at 7:56 PM, Howard Hinnant
> <hinnant_at_[hidden]> wrote:
>> It seems a shame that process_clock does not really meet the proposed
>> standard clock requirements (its now() doesn't return the
>> time_point). That
>> being said, I can see why you didn't. This clock really has 3
>> distinct
>> "time points" and one needs to set each of those three with one
>> system call.
>
> Yep, and I couldn't see any practical downside to the proposed now()
> signature. Other than that, I did try to make process_clock conform.
>
>> If one wanted, one could easily create a user_time_clock wrapper
>> around
>> processor_clock to adapt it to the standard clock requirements if
>> needed.
>
> Yes. Interesting. That hadn't occurred to me.
>
>> Just for general education purposes, here's a portable processor-
>> time clock
>> (just to show how easy it is to build a custom clock):
>>
>> #include <ctime>
>> #include <cstdio>
>> #include <chrono>
>>
>> class processor_clock
>> {
>> public:
>> typedef std::clock_t rep;
>> typedef std::ratio<1, CLOCKS_PER_SEC> period;
>> typedef std::chrono::duration<rep, period> duration;
>> typedef std::chrono::time_point<processor_clock> time_point;
>> static const bool is_monotonic = true;
>>
>> static time_point now() {return
>> time_point(duration(std::clock()));}
>> };
>>
>> int main()
>> {
>> processor_clock::time_point t1 = processor_clock::now();
>> processor_clock::time_point t2 = processor_clock::now();
>> std::printf("%g seconds\n",
>> std::chrono::duration<double>(t2-t1).count());
>> }
>>
>> Output:
>>
>> 4e-06 seconds
>
> I'll add that to the docs. The clock requirements are really nice;
> they are totally minimalist, yet provide all the functionality needed.
>
> Did you look at the boost/chrono/timer.hpp header? It supplies a timer
> template to create a timer from any clock. I'd be curious to get your
> reactionsl

You caught me napping. :-)

It looks like a nice utility.

Comments:

* It looks like you would like to see a standard overload of now:

static time_point now(); // might throw
static time_point now(system::error_code& ec); // nothrow

Please feel free to submit an issue on this.

That being said, I just reviewed several POSIX time functions and it
really looks like they just don't fail. I know the ones on darwin
don't. I know the C standard (and POSIX) say things like:

> The value (time_t)(-1)is returned if the calendar time is not
> available.

This strikes me as a situation where the function either never fails
(it is supported), or always fails (it isn't supported). I'm not
positive that the error_code overload is warranted for this
situation. My preference would be that if the platform doesn't
support system_clock (for example) that code using system_clock not
compile instead of always fail at run time. Thus there would be no
reason to check the error code (or expect an exception from now()).
Currently the only thing [time] has to say on this subject is in
[time.duration]/5:

> Requires: Members of duration shall not throw exceptions other than
> those thrown by the indicated
> operations on their representations.

Perhaps we should widen that sentiment to time_point and clock::now().

* I've written utilities like this in the past. I've always put the
functionality of elapsed() plus a print statement in ~timer() so that
use cases looked like:

int main()
{
     timer _("Entire Program");
     // do stuff
}

Output:

Elapsed time for Entire Program was 15 seconds.

I've had start(), and I think I probably renamed elapsed() to
something like report() (due to the printing functionality), and I
also had stop(). If report() was called prior to ~timer(), without
another start(), then ~timer() did not report(). There was also a way
to construct timer() without implicitly calling start(). Perhaps an
elapsed() would have been a good addition to what I've done in the
past. Wrist watch timer's I've seen have two versions of elapsed:

1. Get the elapsed time and keep the timer going.
2. Get the elapsed time and stop the timer.

Maybe #1 could be handled by elapsed(), and #2 could be handled by
having stop() return the elapsed time?

There are disadvantages to the way I've done it (auto-report): One
doesn't always want a print out, and if one does, one doesn't always
want it to go to the same stream. For me this was always a debugging
utility and thus such matters weren't that important.

Since it did "auto-report", I really liked being able to distinguish
among multiple timer outputs:

void f1()
{
    timer _("f1");
    // ...
}

void f2()
{
    timer _("f2");
    // ...
}

int main()
{
    timer _("main");
    f1();
    f2();
}

Output:

Elapsed time for f1 was 3 seconds.
Elapsed time for f2 was 2 seconds.
Elapsed time for main was 5 seconds.

* I can't imagine ever using any clock but
std::chrono::high_resolution_clock for timer.

Even if high_resolution_clock isn't monotonic, I'm usually using this
utility in a debug/test context and know better than to go resetting
system clocks during a test. On OS X, high_resolution_clock will be
monotonic (if I have anything to say about it).

* Here's one way to get the total time spent in f1(), as opposed to
the time per call:

void f1()
{
     static timer t("Total time spent in f1");
     t.start(); // first start is redundant and ignored
     // ...
     t.stop();
}

One might write a timer-wrapper which put the t.stop() in ~wrapper()
(and took a timer& in its ctor and started it).

void f1()
{
     static timer t("Total time spent in f1");
     timer_start_stop _(t);
     // ...
}

class timer_start_stop
{
     timer& t_;
public:
     explicit timer_start_stop(timer& t) : t_(t) {t_.start();}
     ~timer_start_stop() {t_.stop();}
     timer_start_stop(const timer_start_stop&) = delete;
     timer_start_stop& operator=(const timer_start_stop&) = delete;
};

-Howard


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk