std::chrono::high_resolution_clock::now throwing exception in Safari (when ASM.JS is run in webworker)

133 views
Skip to first unread message

Gaurav Dewan

unread,
Jul 25, 2016, 6:24:48 AM7/25/16
to emscripten-discuss
Based on quick read of C++ specs (although more thorough reading of C++ specs would be required), 
(1) std::chrono::high_resolution_clock::now is declared to be no-except(cannot throw exceptions). 
(2) high_resolution_-clock may be a synonym for system_clock or steady_clock

When calling this function in Safari ASM.JS worker(Mac), 
The test program is same as:
It's just that this asm.js is loaded from javascript webworker.

Function __ZNSt3__16chrono12steady_clock3nowE calls __ZNSt3__120__throw_system_errorEiPKc (via invoke_vii).
Shouldn't emscripten fallback to Date.now() if Performance.now() is not implemented ?

Alon Zakai

unread,
Jul 25, 2016, 1:56:17 PM7/25/16
to emscripten-discuss
Yes, all I can see is code that checks if performance exists first, then uses a fallback if not (on current incoming). Do you have a specific stack trace showing where in the code it fails for you?

--
You received this message because you are subscribed to the Google Groups "emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-disc...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Gaurav Dewan

unread,
Jul 27, 2016, 10:07:59 AM7/27/16
to emscripten-discuss
To reproduce, on emscripten 1.36.5 (incoming branch)
 
(1) here is simple test case (c.cpp)
#include <chrono>
#include <iostream>


int
main
()
{
    std
::cout << "before" << std::endl;
   
auto now = std::chrono::high_resolution_clock::now();
    std
::cout << "after" << std::endl;
   
return 0;
}

(2) Compile it using
 em++ c.cpp -o c.html

(3) In generated c.js, add following line as first line (To simulate Safari/IE/Edge webworker environment restriction on FF/Chrome)
performance={};

Output:
Only before is printed followed by exception (some implementations of boost::chrono::steady_clock::now may throw exception; but here we are using std::chrono )

Reason:

__ZNSt3__26chrono12steady_clock3nowEv (_std::__2::chrono::steady_clock::now())   calls (via invoke_ii)    _clock_gettime(clk_id =1,tp) 
_clock_gettime calls_emscripten_get_now_is_monotonic which return false
_clock_gettime then sets error number and return -1.
__ZNSt3__26chrono12steady_clock3nowEv  on seeing this error throws if exceptions are enabled or continue (with unexpected time value) if exceptions are disabled.
YES, _emscripten_get_now checks if performance exists and then uses a fallback but it is not called due to monotonicity test failure


Other consideration: 
As mentioned in comment, Date.now does not guarantee monotonicty and it may be issue depending on some implementation. An answer here indicate how Date.now can be forced to be monotonic:



Alon Zakai

unread,
Jul 27, 2016, 3:05:35 PM7/27/16
to emscripten-discuss
Ok, I see - the issue isn't that we try to use the performance object when it isn't there, but that when it isn't there, we don't have a monotonic clock, and we report that correctly. That C++ STL functionality happens to require a monotonic clock, so when it finds we don't have that, it throws a C++ exception.

Not sure what we can do here. Forcing Date.now to be monotonic is tricky, it could be very inaccurate and cause surprising behavior.

Alon Zakai

unread,
Jul 27, 2016, 3:06:55 PM7/27/16
to emscripten-discuss
As a workaround, you can polyfill performance and its now() method (with something that forces Date.now() to be monotonic). I'm worried about doing that by default, but if it works for your app it's a simple solution.

Steven Johnson

unread,
May 20, 2019, 7:36:28 PM5/20/19
to emscripten-discuss
...three years later, looks like this bug is still alive and well in Emscripten (I found it via compiling wasm, not asm.js).

I need something like steady_clock() to use for a simple code-benchmarking setup; if I can't rely on std::chrono, what's the recommended replacement?

Floh

unread,
May 21, 2019, 5:53:32 AM5/21/19
to emscripten-discuss
I have a simple cross-platform timing header here which uses the "most accurate time source" on each system:


...however be warned that performance.now() is deliberately inaccurate in browsers since the Spectre/Meltdown apocalypse.

Precision is different in each browser (e.g. Firefox and Safari seem to round to the nearest millisecond), and there may be a random jitter added.

Steven Johnson

unread,
May 21, 2019, 1:21:09 PM5/21/19
to emscripte...@googlegroups.com
Thanks!

For my short-to-medium-term purposes, I only care about performance in d8 and/or Node. 

--
You received this message because you are subscribed to the Google Groups "emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-disc...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages