Boost logo

Boost :

Subject: Re: [boost] [chrono/date] class names
From: Howard Hinnant (howard.hinnant_at_[hidden])
Date: 2013-05-12 21:33:07


On May 11, 2013, at 7:13 PM, Vicente J. Botet Escriba <vicente.botet_at_[hidden]> wrote:

> What do you think to using namespaces instead of prefixes?
> This will allow to have checked and unchecked unit specifiers as well.
>
> using chrono::checked;
> serial_date dt = may/11/year(2013);
>
> using chrono::unchecked;
> serial_date dt = may/11/year(2013);

This is an interesting idea. However I'm having serious doubts that we want duplicate checked and unchecked API's.

My 2011 chrono paper clearly got checked API's wrong, at least in the implementation. There was way too much redundant checking going on. There was not enough attention paid to the issue of reducing redundant validation.

N3344 rightly pointed out the performance issues with my work.

That being said, I now think it is quite possible that N3344 came to a few incorrect conclusions. I think we need to aggressively investigate the possibility of just having:

checked field types
unchecked serial types

If we give up checking on range, the unchecked and checked serial types are the exact same thing. This is what chrono::duration and chrono::time_point do.

With constexpr as a tool in the toolbox, and with careful thought to avoid redundant validation, checked field types seem very affordable performance wise. And the simplicity gained by not having checked and unchecked field types that are identical in API and nearly identical in performance is extremely compelling. More work needs to be done to ensure that this is indeed a viable approach. However the payoff is huge, and thus worth investigating.

N3344 benchmarks:

3.3.1 Creators:

> This benchmark creates date objects in a loop, repeatedly creating three fixed date values: 2000/1/1, 2000/12/31, and 2009/5/1.
>
> The objective of this benchmark is to measure the performance of the value constructor of each date implementation.

With the use of constexpr, the validation checking for this benchmark is completely done at compile time. I admit that the benchmark needs to be improved so that it would actually measure the intended cost of conversion from run-time field information to a serial date. But my point is that this effort was not done in N3344, quite likely due to lack of constexpr-enabled compilers.

3.3.2 Accessors

> This benchmark repeatedly extracts the year, month, and day from a constant date object having the value 2001/1/1, by invoking the year, month, and day accessors.

Again, this benchmark is all compile-time validation and computation.

3.3.3 Increase Day

> This benchmark repeatedly advances a date object by one day, starting from date 1/1/1 and incre- menting 3652061 times.

For a serial date type, such as chrono::time_point with a period of days, this is the exact same expense as integral increment.

3.3.4 Increase Month

> This benchmark repeatedly advances a date object by one month, starting from date 1/1/1 up to the year 9000.

This still needs work, however I have confidence that all validation can be removed from a checked field type for this benchmark. The initial date is constexpr'd valid, and adding n months to this date is compile-time-provable valid.

3.3.5 Array Sorting

No validation issues.

3.3.6 Modified Following

This is the most interesting benchmark. This is where we should really be performance testing checked vs unchecked types. I strongly suspect that with checked field types and unchecked serial types, this benchmark will not motivate the need for unchecked field types nor checked serial types. But this is work in progress.

3.3.7 Packed Calendar

Needs more investigation with respect to performance. I strongly suspect that with checked field types and unchecked serial types, this benchmark will not motivate the need for unchecked field types nor checked serial types. But this is work in progress.

---------

One of the conclusions that I feel N3344 got very right, but with the wrong syntax is this member function of date:

   void get_yearmonthday(int *year, int *month, int *day) const;

N3344 is biased towards "date" being a serial date type. And the above suggested member is much better expressed as a conversion from the serial date type to the field date types.

Bottom line: N3344 has some very valid criticisms. But we should not limit ourselves to addressing those criticisms in exactly the way N3344 suggests. There are other (and I think better) possibilities. And I really dislike the checked/unchecked interfaces when the performance difference between the two is only a few percent (more work needed to absolutely nail down that this is in fact the case).

Howard


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