emscripten icon indicating copy to clipboard operation
emscripten copied to clipboard

evaluation of std::sin in C++ is slower than in JS directly

Open adam-ce opened this issue 3 months ago • 5 comments

When executing the code below, the c++ execution is way slower than the JS one:

chrome on linux:

cpp_time: 26.043s
js_time: 2.685s

firefox on linux:

cpp_time: 28.458s
js_time: 2.711s

when compiling with gcc 11.4, i get cpp_time: 4.217s (yes, that's slower than using JS). timings on windows are similar.

I asked about it on stackoverflow before.

There, user21489919 reported, that in his tiny-wasm-runtime, the c++ sin is almost as fast as the JS version (on chrome, on FF the C++ version is faster). The reason seems to be, that tiny-wasm-runtime calls JS in its implementation of sin.

So this makes me believe, that there is some performance issue with emscripten, hence the bugreport.

Code:

#include <chrono>
#include <iostream>
#include <cmath>

#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif

int main() {
    const auto n_iter = 50u;
    
    double cpp_sum = 0;
    const auto cpp_begin = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < n_iter; ++i) {
        double sum = 1.0;
        for (int t = 0; t < 5000000; ++t) {
            sum += std::sin(double(t));
        }
        cpp_sum = sum;
    };
    const auto cpp_time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - cpp_begin).count();
    std::cout << "cpp_sum: " << cpp_sum << std::endl;
    std::cout << "cpp_time: " << double(cpp_time) / 1000.0 << "s" << std::endl;
 
#ifdef __EMSCRIPTEN__
    double js_sum = 0;
    const auto js_begin = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < n_iter; ++i) {
        js_sum = EM_ASM_DOUBLE({
            let sum = 1;
            for (let i = 0; i < 5000000; i++) {
                sum = sum + Math.sin(i);
            }
            return sum;
        });
    };
    const auto js_time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - js_begin).count();
    std::cout << "js_sum: " << js_sum << std::endl;
    std::cout << "js_time: " << double(js_time) / 1000.0 << "s" << std::endl;
    
#endif
    return 0;
}

Version of emscripten/emsdk: I ran the code with the version 3.1.56 now, but several older version have the same performance hit.

emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.56 (cf90417346b78455089e64eb909d71d091ecc055) clang version 19.0.0git (https:/github.com/llvm/llvm-project 34ba90745fa55777436a2429a51a3799c83c6d4c) Target: wasm32-unknown-emscripten Thread model: posix InstalledDir: /home/madam/bin/emsdk/upstream/bin

Full link command and output with -v appended:

em++ ./main.cpp -o main.html -v "/home/madam/bin/emsdk/upstream/bin/clang++" -target wasm32-unknown-emscripten -fignore-exceptions -fvisibility=default -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr --sysroot=/home/madam/bin/emsdk/upstream/emscripten/cache/sysroot -DEMSCRIPTEN -Xclang -iwithsysroot/include/fakesdl -Xclang -iwithsysroot/include/compat -v ./main.cpp -c -o /tmp/emscripten_temp_lpd1_wvw/main_0.o clang version 19.0.0git (https:/github.com/llvm/llvm-project 34ba90745fa55777436a2429a51a3799c83c6d4c) Target: wasm32-unknown-emscripten Thread model: posix InstalledDir: /home/madam/bin/emsdk/upstream/bin (in-process) "/home/madam/bin/emsdk/upstream/bin/clang-19" -cc1 -triple wasm32-unknown-emscripten -emit-obj -mrelax-all -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name main.cpp -mrelocation-model static -mframe-pointer=none -ffp-contract=on -fno-rounding-math -mconstructor-aliases -target-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/home/madam/Documents/emscripten_perf_bug -v -fcoverage-compilation-dir=/home/madam/Documents/emscripten_perf_bug -resource-dir /home/madam/bin/emsdk/upstream/lib/clang/19 -D EMSCRIPTEN -isysroot /home/madam/bin/emsdk/upstream/emscripten/cache/sysroot -internal-isystem /home/madam/bin/emsdk/upstream/emscripten/cache/sysroot/include/wasm32-emscripten/c++/v1 -internal-isystem /home/madam/bin/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1 -internal-isystem /home/madam/bin/emsdk/upstream/lib/clang/19/include -internal-isystem /home/madam/bin/emsdk/upstream/emscripten/cache/sysroot/include/wasm32-emscripten -internal-isystem /home/madam/bin/emsdk/upstream/emscripten/cache/sysroot/include -fdeprecated-macro -ferror-limit 19 -fvisibility=default -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcxx-exceptions -fignore-exceptions -fexceptions -fcolor-diagnostics -iwithsysroot/include/fakesdl -iwithsysroot/include/compat -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr -o /tmp/emscripten_temp_lpd1_wvw/main_0.o -x c++ ./main.cpp clang -cc1 version 19.0.0git based upon LLVM 19.0.0git default target x86_64-unknown-linux-gnu ignoring nonexistent directory "/home/madam/bin/emsdk/upstream/emscripten/cache/sysroot/include/wasm32-emscripten/c++/v1" ignoring nonexistent directory "/home/madam/bin/emsdk/upstream/emscripten/cache/sysroot/include/wasm32-emscripten" #include "..." search starts here: #include <...> search starts here: /home/madam/bin/emsdk/upstream/emscripten/cache/sysroot/include/fakesdl /home/madam/bin/emsdk/upstream/emscripten/cache/sysroot/include/compat /home/madam/bin/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1 /home/madam/bin/emsdk/upstream/lib/clang/19/include /home/madam/bin/emsdk/upstream/emscripten/cache/sysroot/include End of search list. /home/madam/bin/emsdk/upstream/bin/clang --version /home/madam/bin/emsdk/upstream/bin/wasm-ld -o main.wasm /tmp/emscripten_temp_lpd1_wvw/main_0.o -L/home/madam/bin/emsdk/upstream/emscripten/cache/sysroot/lib/wasm32-emscripten -lGL-getprocaddr -lal -lhtml5 -lstubs-debug -lnoexit -lc-debug -ldlmalloc -lcompiler_rt -lc++-noexcept -lc++abi-debug-noexcept -lsockets -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr /tmp/tmpzvrhcznelibemscripten_js_symbols.so --strip-debug --export=emscripten_stack_get_end --export=emscripten_stack_get_free --export=emscripten_stack_get_base --export=emscripten_stack_get_current --export=emscripten_stack_init --export=stackAlloc --export=stackSave --export=stackRestore --export=__get_temp_ret --export=__set_temp_ret --export=__wasm_call_ctors --export-if-defined=__start_em_asm --export-if-defined=__stop_em_asm --export-if-defined=__start_em_lib_deps --export-if-defined=__stop_em_lib_deps --export-if-defined=__start_em_js --export-if-defined=__stop_em_js --export-if-defined=main --export-if-defined=__main_argc_argv --export-if-defined=fflush --export-table -z stack-size=65536 --no-growable-memory --initial-heap=16777216 --no-entry --stack-first --table-base=1 /home/madam/bin/emsdk/upstream/bin/llvm-objcopy main.wasm main.wasm --remove-section=.debug* --remove-section=producers /home/madam/bin/emsdk/upstream/bin/wasm-emscripten-finalize --dyncalls-i64 --pass-arg=legalize-js-interface-exported-helpers main.wasm -o main.wasm --detect-features /home/madam/bin/emsdk/node/16.20.0_64bit/bin/node /home/madam/bin/emsdk/upstream/emscripten/src/compiler.mjs /tmp/tmpmv73rwfy.json /home/madam/bin/emsdk/node/16.20.0_64bit/bin/node /home/madam/bin/emsdk/upstream/emscripten/tools/preprocessor.mjs /tmp/emscripten_temp_lpd1_wvw/settings.js shell.html

adam-ce avatar Mar 31 '24 08:03 adam-ce