-Filip
> On May 23, 2016, at 12:12 AM, Michal Debski <m.deb...@samsung.com> wrote:
> 
> Please this example: http://ideone.com/c640Xd
> 
I'm not going to write "WTF::now<std::chrono::system_clock>()" every time I 
want the time. That's awful!

One of the problems with chrono is the use of awkward templates throughout the 
API. Your solution makes this worse. 
> From cppreference:
> 
> "(time_point) is implemented as if it stores a value of typeDuration 
> indicating the time interval from the start of the Clock's epoch."
> 
> "If Rep is floating point, then the duration can represent fractions of 
> ticks."
> 
> http://en.cppreference.com/w/cpp/chrono/time_point
> 
> http://en.cppreference.com/w/cpp/chrono/duration
> 
>  
> 
> time_point still remembers which clock it belongs to, see the specialization 
> now() returns.  
> 
> The only problem I see is that conversion from fractional duration with 
> Infinite value to integer duration is undefined. But I assume it would be 
> forbiden to use integer based chrono altogether.
> 
That seems like a tough thing to guarantee.
> As for the last point I don't understand what do you mean by non-canonical.
> 
According to Merriam-Webster, canonical means: conforming to a general rule or 
acceptable procedure. I don't think that your approach is the normal, generally 
accepted way to use std::chrono. 
> It uses the API as intended, why would c++ expose the templates if not for 
> specializing the behaviour? Also move operator is not canonical in WTF 
> strictly speaking.
> 
>  
> 
> I just remember about ugly bugs in MediaTime arithmetics.
> 
>  
> 
> Best regards,
> 
> Michal Debski
> 
>  
> 
> ------- Original Message -------
> 
> Sender : Filip Pizlo<fpi...@apple.com>
> 
> Date : May 23, 2016 07:32 (GMT+01:00)
> 
> Title : Re: [webkit-dev] RFC: stop using std::chrono, go back to using 
> doubles for time
> 
>  
> 
> 
> 
>> On May 22, 2016, at 10:46 PM, Michal Debski <m.deb...@samsung.com> wrote:
>> 
>> Hi,
>> 
>>  
>> 
>> sorry but this really bugs me. Isn't this enough?
>> 
>>  
>> 
>> namespace WTF {
>> 
>> using nanoseconds = std::chrono::duration<double, std::nano>;
>> using microseconds = std::chrono::duration<double, std::micro>;
>> using milliseconds = std::chrono::duration<double, std::milli>;
>> using seconds = std::chrono::duration<double>;
>> using minutes = std::chrono::duration<double, std::ratio<60>>;
>> using hours = std::chrono::duration<double, std::ratio<3600>>;
>> 
>> 
>> template <class Clock>
>> std::chrono::time_point<Clock, seconds> now()
>> {
>>     return Clock::now();
>> }
>> 
> Can you clarify how this returns fractional seconds?
> 
> Note that your code snippets are not enough to cover WebKit's use of clocks. 
> For example we would need wall clock and monotonic clock classes with 
> time_point types. If we have to significantly customize std::chrono and 
> forbid some but not all of its API, then probably the total amount of code to 
> do this would be comparable to writing our own Seconds/WallTime/MonotonicTime 
> classes.
>> 
>> }
>> 
>>  
>> 
>> and forbid using std::chrono::clock::now()/durations with check-style. It 
>> seems like the best of both worlds.
>> 
> It's an interesting perspective. But I would find it confusing if we used a 
> non-canonical kind of std::chrono. And I'm not convinced that the changes 
> required to make this work are as simple as what you say. 
>> Oh and the infinity:
>> 
>>  
>> 
>> namespace std {
>> namespace chrono {
>> 
>> template<>
>> struct duration_values<double> {
>>     static constexpr double min() { return 
>> -std::numeric_limits<double>::infinity(); }
>>     static constexpr double zero() { return .0; }
>>     static constexpr double max() { return 
>> std::numeric_limits<double>::infinity(); }
>> };
>> 
>> }
>> } 
>> 
>> Best regards,
>> Michal Debski
>> 
>>  
>> 
>> ------- Original Message -------
>> 
>> Sender : Filip Pizlo<fpi...@apple.com>
>> 
>> Date : May 23, 2016 02:41 (GMT+01:00)
>> 
>> Title : [webkit-dev] RFC: stop using std::chrono, go back to using doubles 
>> for time
>> 
>>  
>> 
>> Hi everyone!
>> 
>> I’d like us to stop using std::chrono and go back to using doubles for time. 
>>  First I list the things that I think we wanted to get from std::chrono - 
>> the reasons why we started switching to it in the first place.  Then I list 
>> some disadvantages of std::chrono that we've seen from fixing 
>> std::chrono-based code.  Finally I propose some options for how to use 
>> doubles for time.
>> 
>> Why we switched to std::chrono
>> 
>> A year ago we started using std::chrono for measuring time.  std::chrono has 
>> a rich typesystem for expressing many different kinds of time.  For example, 
>> you can distinguish between an absolute point in time and a relative time.  
>> And you can distinguish between different units, like nanoseconds, 
>> milliseconds, etc.
>> 
>> Before this, we used doubles for time.  std::chrono’s advantages over 
>> doubles are:
>> 
>> Easy to remember what unit is used: We sometimes used doubles for 
>> milliseconds and sometimes for seconds.  std::chrono prevents you from 
>> getting the two confused.
>> 
>> Easy to remember what kind of clock is used: We sometimes use the monotonic 
>> clock and sometimes the wall clock (aka the real time clock).  Bad things 
>> would happen if we passed a time measured using the monotonic clock to 
>> functions that expected time measured using the wall clock, and vice-versa.  
>> I know that I’ve made this mistake in the past, and it can be painful to 
>> debug.
>> 
>> In short, std::chrono uses compile-time type checking to catch some bugs.
>> 
>> Disadvantages of using std::chrono
>> 
>> We’ve seen some problems with std::chrono, and I think that the problems 
>> outweigh the advantages.  std::chrono suffers from a heavily templatized API 
>> that results in template creep in our own internal APIs.  std::chrono’s 
>> default of integers without overflow protection means that math involving 
>> std::chrono is inherently more dangerous than math involving double.  This 
>> is particularly bad when we use time to speak about timeouts.
>> 
>> Too many templates: std::chrono uses templates heavily.  It’s overkill for 
>> measuring time.  This leads to verbosity and template creep throughout 
>> common algorithms that take time as an argument.  For example if we use 
>> doubles, a method for sleeping for a second might look like 
>> sleepForSeconds(double).  This works even if someone wants to sleep for a 
>> nanoseconds, since 0.000001 is easy to represent using a double.  Also, 
>> multiplying or dividing a double by a small constant factor (1,000,000,000 
>> is small by double standards) is virtually guaranteed to avoid any loss of 
>> precision.  But as soon as such a utility gets std::chronified, it becomes a 
>> template.  This is because you cannot have sleepFor(std::chrono::seconds), 
>> since that wouldn’t allow you to represent fractions of seconds.  This 
>> brings me to my next point.
>> 
>> Overflow danger: std::chrono is based on integers and its math methods do 
>> not support overflow protection.  This has led to serious bugs like 
>> https://bugs.webkit.org/show_bug.cgi?id=157924.  This cancels out the 
>> “remember what unit is used” benefit cited above.  It’s true that I know 
>> what type of time I have, but as soon as I duration_cast it to another unit, 
>> I may overflow.  The type system does not help!  This is insane: std::chrono 
>> requires you to do more work when writing multi-unit code, so that you 
>> satisfy the type checker, but you still have to be just as paranoid around 
>> multi-unit scenarios.  Forgetting that you have milliseconds and using it as 
>> seconds is trivially fixable.  But if std::chrono flags such an error and 
>> you fix it with a duration_cast (as any std::chrono tutorial will tell you 
>> to do), you’ve just introduced an unchecked overflow and such unchecked 
>> overflows are known to cause bugs that manifest as pages not working 
>> correctly.
>> 
>> I think that doubles are better than std::chrono in multi-unit scenarios.  
>> It may be possible to have std::chrono work with doubles, but this probably 
>> implies us writing our own clocks.  std::chrono’s default clocks use 
>> integers, not doubles.  It also may be possible to teach std::chrono to do 
>> overflow protection, but that would make me so sad since using double means 
>> not having to worry about overflow at all.
>> 
>> The overflow issue is interesting because of its implications for how we do 
>> timeouts.  The way to have a method with an optional timeout is to do one of 
>> these things:
>> 
>> - Use 0 to mean no timeout.
>> - Have one function for timeout and one for no timeout.
>> - Have some form of +Inf or INT_MAX to mean no timeout.  This makes so much 
>> mathematical sense.
>> 
>> WebKit takes the +Inf/INT_MAX approach.  I like this approach the best 
>> because it makes the most mathematical sense: not giving a timeout is 
>> exactly like asking for a timeout at time-like infinity.  When used with 
>> doubles, this Just Works.  +Inf is greater than any value and it gets 
>> preserved properly in math (+Inf * real = +Inf, so it survives gracefully in 
>> unit conversions; +Inf + real = +Inf, so it also survives 
>> absolute-to-relative conversions).
>> 
>> But this doesn’t work with std::chrono.  The closest thing to +Inf is 
>> duration::max(), i.e. some kind of UINT_MAX, but this is guaranteed to 
>> overflow anytime it’s converted to a more precise unit of time 
>> (nanoseconds::max() converted to milliseconds is something bogus).  It 
>> appears that std::chrono doesn’t have a good story for infinite timeout, 
>> which means that anyone writing a function that can optionally have a 
>> timeout is going to have a bad time.  We have plenty of such functions in 
>> WebKit.  For example, I’m not sure how to come up with a feel-good solution 
>> to https://bugs.webkit.org/show_bug.cgi?id=157937 so long as we use 
>> std::chrono.
>> 
>> Going back to doubles
>> 
>> Considering these facts, I propose that we switch back to using doubles for 
>> time.  We can either simply revert to the way we used doubles before, or we 
>> can come up with some more sophisticated approach that blends the best of 
>> both worlds.  I prefer plain doubles because I love simplicity.
>> 
>> Simply revert to our old ways: I like this approach the best because it 
>> involves only very simple changes.  Prior to std::chrono, we used a double 
>> to measure time in seconds.  It was understood that seconds was the default 
>> unit.  We would use both monotonic and wall clocks, and we used double for 
>> both of them.
>> 
>> Come up with a new type system: Having learned from std::chrono and doubles, 
>> it seems that the best typesystem for time would comprise three classes: 
>> Seconds, WallTime, and MonotonicTime.  Seconds would be a class that holds a 
>> double and supports +/+=/-/-=/</<=/>/>=/==/!= operations, as well as 
>> conversions to a raw double for when you really need it.  WallTime and 
>> MonotonicTime would be wrappers for Seconds with a more limited set of 
>> available operations.  You can convert WallTime or MonotonicTime to Seconds 
>> and vice-versa, but some operators are overloaded to make casts unnecessary 
>> in most cases (WallTime + Seconds = WallTime, WallTime - WallTime = Seconds, 
>> etc).  This would save us from forgetting the unit or the clock.  The name 
>> of the Seconds class is a dead give-away, and WallTime and MonotonicTime 
>> will not yield you a value that is unit-sensitive unless you say something 
>> like WallTime::toSeconds().  There will be no easy way to convert WallTime 
>> to MonotonicTime and vice-versa, since we want to discourage such 
>> conversions.
>> 
>> Personally I feel very comfortable with doubles for time.  I like to put the 
>> word “Seconds” into variable names and function names 
>> (waitForSeconds(double) is a dead give-away).  On the other hand, I sort of 
>> like the idea of a type system to protect clock mix-ups.  I think that’s the 
>> biggest benefit we got from std::chrono.
>> 
>> If it was entirely up to me, I’d go for doubles.  I think that there needs 
>> to be a high burden of proof for using types to catch semantic bugs.  A type 
>> system *will* slow you down when writing code, so the EV (expected value) of 
>> the time savings from bugs caught early needs to be greater than the EV of 
>> the time lost due to spoonfeeding the compiler or having to remember how to 
>> use those classes.  Although I know that using doubles sometimes meant we 
>> had bugs, I don’t think they were frequent or severe enough for the odds to 
>> be good for the Seconds/WallTime/MonotonicTime solution.
>> 
>> Thoughts?
>> 
>> -Filip
>> 
>>  
>> 
>>  
>> 
>> _______________________________________________
>> webkit-dev mailing list
>> webkit-dev@lists.webkit.org
>> https://lists.webkit.org/mailman/listinfo/webkit-dev
>  
> 
>  
> 
> _______________________________________________
> webkit-dev mailing list
> webkit-dev@lists.webkit.org
> https://lists.webkit.org/mailman/listinfo/webkit-dev
_______________________________________________
webkit-dev mailing list
webkit-dev@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-dev

Reply via email to