3 comments

  • barishnamazov3 hours ago
    I built a local competitive programming judge a while back where I fell into the exact trap of manually correlating steady_clock and system_clock.<p>I was timestamping everything using steady_clock to strictly enforce the time limits, and then just applied a calculated offset to convert that to wall time for the &quot;Submission Date&quot; display. It worked in testing, but during a long stress-test session, my laptop did an NTP sync. The logs then showed submissions appearing to happen before the source code file was last modified, which confused the caching logic. I was essentially betting that system_clock was stable relative to steady_clock over the process lifetime.<p>I eventually refactored to exactly what the article suggests: use steady_clock strictly for the runtime enforcement (is duration &lt; 2.0s?), but capture system_clock::now() explicitly at the submission boundary for the logs, rather than trying to do math on the steady timestamp.<p>Also, +1 for std::chrono::round in C++20. I’ve seen code where duration_cast was used to &quot;round&quot; execution times to milliseconds for display, but it was silently flooring them. In a competitive programming context, reporting 1000ms when the actual time was 1000.9ms is a misleading difference because the latter gets Time Limit Exceeded error. Explicit rounding makes the intent much clearer.
  • loeg3 hours ago
    The thing I ran into most recently is that std::chrono (weirdly?) only supports clocks with compile-time fixed fractional conversion to reference time (~seconds). E.g., you can&#x27;t implement a std::chrono clock where the count() unit is the native CPU&#x27;s cycle counter, which will have some runtime-determined conversion to seconds. The types make it impossible.
    • mpyne1 hour ago
      std::chrono counts the number of ticks of a given periodicity. The periodicity does have to be a known compile-time ratio expressible as a fraction of seconds, but you can use a floating-type type to count the number of ticks.<p>std::chrono is meant to take advantage of information about periodicity at compile time, but if you want to count in terms of a dynamic periodicity not known until runtime, you can still do things. E.g. use time_t and some wrapper functions, or just pick one (or several) std::chrono base durations such as standardizing on nanoseconds, and then just count floating-point ticks.
  • cyberax3 hours ago
    C++ chrono is weird. It&#x27;s both over-abstracted and yet has some thoughtless features that just negate this over-abstraction.<p>I remember not being able to represent the time in fractional units, like tertias (1&#x2F;60-th of a second) but that was mostly an academic problem. More importantly, it was not possible to express duration as a compound object. I wanted to be able to represent the dates with nanosecond precision, but with more than 250 years of range. I think it is still not possible?
    • mpyne1 hour ago
      Fractional time shouldn&#x27;t be an issue as long as the ratio is a rational number. It&#x27;s how durations are already handled behind the scenes.<p>Likewise it&#x27;s annoying to cook up your own type, but as long as you can come up with &#x27;number of ticks&#x27; type that acts like an arithmetic type then it should work with std::chrono. E.g. if I just Boost&#x27;s Multiprecision library as a quick example:<p><pre><code> #include &lt;chrono&gt; #include &lt;iostream&gt; #include &lt;boost&#x2F;multiprecision&#x2F;cpp_int.hpp&gt; using namespace std::chrono_literals; int main() { using BigInt = boost::multiprecision::uint128_t; using BigNanos = std::chrono::duration&lt;BigInt, std::nano&gt;; std::cout &lt;&lt; &quot;Count for 1s: &quot; &lt;&lt; BigNanos(1s).count() &lt;&lt; &quot;\n&quot;; std::cout &lt;&lt; &quot;Count for 300 years: &quot; &lt;&lt; BigNanos(std::chrono::years(300)).count() &lt;&lt; &quot;\n&quot;; } </code></pre> Then that code (when compiled with -std=c++20 or better) should output:<p>Count for 10s: 1000000000 Count for 300 years: 9467085600000000000<p>If you&#x27;re willing to use gcc&#x2F;clang builtins for 128-bit types you won&#x27;t even need Boost or your own custom type to do basic arithmetic (but serializing the result may be difficult, not sure how gcc&#x2F;clang handle that for custom 128-bit types).
      • cyberax1 hour ago
        Yes, that was my problem. I could use the emulated uint128_t, but not a seconds+nano seconds pair. I need to re-check why...