Why is WebAssembly this slow as compared to JavaScript?











up vote
3
down vote

favorite
2












Today I decided to play around with WebAssembly for the very first time. So, I wrote this little Fibonacci program in C++:



#include <iostream>
#include <chrono>

int fib(int n) {
if(n==0) {
return 0;
} else if(n==1) {
return 1;
} else {
return fib(n-1) + fib(n-2);
}
}

int main() {
std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now();
int sum = 0;

for (int i = 0; i < 35; ++i) {
sum += fib(i);
}

std::chrono::high_resolution_clock::time_point t2 = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::milli> dur = t2 - t1;

std::cout << sum << std::endl;
std::cout << dur.count() << std::endl;
}


And compiled it into Web Assembly (WA from now onwards) using the following command:



emcc fib.cpp -s WASM=1 -o fib.html


Then, after loading the resulting .html file into the browser, the output I got was 14930351 592.8, which means that WA took almost 600 milliseconds.



Then, I wrote a JS equivalent of the same program, as follows:



export function fib(n) {
return n === 0 ? 0 : (n === 1 ? 1 : fib(n-1) + fib(n-2));
}

export function fibSum(n) {
let sum = 0;
for (let i = 0; i < n; i++) {
sum += fib(i)
}

return sum;
}


I used performance.now() to measure the elapsed time in milliseconds to calculate fibSum(35), which gave an output of 347.200 milliseconds on Chrome.



I get it that WA is very new hence the compiler must be missing some optimisations as compared to the V8 engine and it takes time to call WA code from the browser and everything but I was not expecting it to be this slow.



Thoughts? Have I not created a proper test case to compare the two?










share|improve this question




















  • 1




    Can you please remove all the std::chrono stuff and std::cout from your code and try again? I made a .js file with the js code you provided and tested it and it took approximately 150ms when I tested it with (node fibjs.js). Then, I compiled the C code twice: once with the chrono stuff, once without. For the second version, I put the time-measuring code in the generated js file, before and after the run function. The first compiled version took 300+ms, but the second one took 130-150ms, so very close to the pure js code.
    – Adi
    Nov 18 at 13:17










  • So...based on my results, I guess that using a lot of libraries or complex functions also affect the compiled js code.
    – Adi
    Nov 18 at 13:18










  • @Adi Can you please guide me where to put that time-measuring code in generated fib.js file? I tried removing all the chrono stuff and putting time-measuring code in the run(args) method of the generated JS file but no difference.
    – Rajat Saxena
    Nov 18 at 13:30






  • 1




    At the end of the fib.js file, there is a call to the run function: run();; I analyzed the code and basically that is the entry point of the program. You can use a simple console.time('test'); run(); console.timeEnd('test'); to measure the time.
    – Adi
    Nov 18 at 14:01








  • 1




    You're also not building with optimizations (emcc -O3 or -Os).
    – Veedrac
    Nov 19 at 5:05

















up vote
3
down vote

favorite
2












Today I decided to play around with WebAssembly for the very first time. So, I wrote this little Fibonacci program in C++:



#include <iostream>
#include <chrono>

int fib(int n) {
if(n==0) {
return 0;
} else if(n==1) {
return 1;
} else {
return fib(n-1) + fib(n-2);
}
}

int main() {
std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now();
int sum = 0;

for (int i = 0; i < 35; ++i) {
sum += fib(i);
}

std::chrono::high_resolution_clock::time_point t2 = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::milli> dur = t2 - t1;

std::cout << sum << std::endl;
std::cout << dur.count() << std::endl;
}


And compiled it into Web Assembly (WA from now onwards) using the following command:



emcc fib.cpp -s WASM=1 -o fib.html


Then, after loading the resulting .html file into the browser, the output I got was 14930351 592.8, which means that WA took almost 600 milliseconds.



Then, I wrote a JS equivalent of the same program, as follows:



export function fib(n) {
return n === 0 ? 0 : (n === 1 ? 1 : fib(n-1) + fib(n-2));
}

export function fibSum(n) {
let sum = 0;
for (let i = 0; i < n; i++) {
sum += fib(i)
}

return sum;
}


I used performance.now() to measure the elapsed time in milliseconds to calculate fibSum(35), which gave an output of 347.200 milliseconds on Chrome.



I get it that WA is very new hence the compiler must be missing some optimisations as compared to the V8 engine and it takes time to call WA code from the browser and everything but I was not expecting it to be this slow.



Thoughts? Have I not created a proper test case to compare the two?










share|improve this question




















  • 1




    Can you please remove all the std::chrono stuff and std::cout from your code and try again? I made a .js file with the js code you provided and tested it and it took approximately 150ms when I tested it with (node fibjs.js). Then, I compiled the C code twice: once with the chrono stuff, once without. For the second version, I put the time-measuring code in the generated js file, before and after the run function. The first compiled version took 300+ms, but the second one took 130-150ms, so very close to the pure js code.
    – Adi
    Nov 18 at 13:17










  • So...based on my results, I guess that using a lot of libraries or complex functions also affect the compiled js code.
    – Adi
    Nov 18 at 13:18










  • @Adi Can you please guide me where to put that time-measuring code in generated fib.js file? I tried removing all the chrono stuff and putting time-measuring code in the run(args) method of the generated JS file but no difference.
    – Rajat Saxena
    Nov 18 at 13:30






  • 1




    At the end of the fib.js file, there is a call to the run function: run();; I analyzed the code and basically that is the entry point of the program. You can use a simple console.time('test'); run(); console.timeEnd('test'); to measure the time.
    – Adi
    Nov 18 at 14:01








  • 1




    You're also not building with optimizations (emcc -O3 or -Os).
    – Veedrac
    Nov 19 at 5:05















up vote
3
down vote

favorite
2









up vote
3
down vote

favorite
2






2





Today I decided to play around with WebAssembly for the very first time. So, I wrote this little Fibonacci program in C++:



#include <iostream>
#include <chrono>

int fib(int n) {
if(n==0) {
return 0;
} else if(n==1) {
return 1;
} else {
return fib(n-1) + fib(n-2);
}
}

int main() {
std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now();
int sum = 0;

for (int i = 0; i < 35; ++i) {
sum += fib(i);
}

std::chrono::high_resolution_clock::time_point t2 = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::milli> dur = t2 - t1;

std::cout << sum << std::endl;
std::cout << dur.count() << std::endl;
}


And compiled it into Web Assembly (WA from now onwards) using the following command:



emcc fib.cpp -s WASM=1 -o fib.html


Then, after loading the resulting .html file into the browser, the output I got was 14930351 592.8, which means that WA took almost 600 milliseconds.



Then, I wrote a JS equivalent of the same program, as follows:



export function fib(n) {
return n === 0 ? 0 : (n === 1 ? 1 : fib(n-1) + fib(n-2));
}

export function fibSum(n) {
let sum = 0;
for (let i = 0; i < n; i++) {
sum += fib(i)
}

return sum;
}


I used performance.now() to measure the elapsed time in milliseconds to calculate fibSum(35), which gave an output of 347.200 milliseconds on Chrome.



I get it that WA is very new hence the compiler must be missing some optimisations as compared to the V8 engine and it takes time to call WA code from the browser and everything but I was not expecting it to be this slow.



Thoughts? Have I not created a proper test case to compare the two?










share|improve this question















Today I decided to play around with WebAssembly for the very first time. So, I wrote this little Fibonacci program in C++:



#include <iostream>
#include <chrono>

int fib(int n) {
if(n==0) {
return 0;
} else if(n==1) {
return 1;
} else {
return fib(n-1) + fib(n-2);
}
}

int main() {
std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now();
int sum = 0;

for (int i = 0; i < 35; ++i) {
sum += fib(i);
}

std::chrono::high_resolution_clock::time_point t2 = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::milli> dur = t2 - t1;

std::cout << sum << std::endl;
std::cout << dur.count() << std::endl;
}


And compiled it into Web Assembly (WA from now onwards) using the following command:



emcc fib.cpp -s WASM=1 -o fib.html


Then, after loading the resulting .html file into the browser, the output I got was 14930351 592.8, which means that WA took almost 600 milliseconds.



Then, I wrote a JS equivalent of the same program, as follows:



export function fib(n) {
return n === 0 ? 0 : (n === 1 ? 1 : fib(n-1) + fib(n-2));
}

export function fibSum(n) {
let sum = 0;
for (let i = 0; i < n; i++) {
sum += fib(i)
}

return sum;
}


I used performance.now() to measure the elapsed time in milliseconds to calculate fibSum(35), which gave an output of 347.200 milliseconds on Chrome.



I get it that WA is very new hence the compiler must be missing some optimisations as compared to the V8 engine and it takes time to call WA code from the browser and everything but I was not expecting it to be this slow.



Thoughts? Have I not created a proper test case to compare the two?







javascript performance web webassembly






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 18 at 12:40

























asked Nov 18 at 12:30









Rajat Saxena

1,64023351




1,64023351








  • 1




    Can you please remove all the std::chrono stuff and std::cout from your code and try again? I made a .js file with the js code you provided and tested it and it took approximately 150ms when I tested it with (node fibjs.js). Then, I compiled the C code twice: once with the chrono stuff, once without. For the second version, I put the time-measuring code in the generated js file, before and after the run function. The first compiled version took 300+ms, but the second one took 130-150ms, so very close to the pure js code.
    – Adi
    Nov 18 at 13:17










  • So...based on my results, I guess that using a lot of libraries or complex functions also affect the compiled js code.
    – Adi
    Nov 18 at 13:18










  • @Adi Can you please guide me where to put that time-measuring code in generated fib.js file? I tried removing all the chrono stuff and putting time-measuring code in the run(args) method of the generated JS file but no difference.
    – Rajat Saxena
    Nov 18 at 13:30






  • 1




    At the end of the fib.js file, there is a call to the run function: run();; I analyzed the code and basically that is the entry point of the program. You can use a simple console.time('test'); run(); console.timeEnd('test'); to measure the time.
    – Adi
    Nov 18 at 14:01








  • 1




    You're also not building with optimizations (emcc -O3 or -Os).
    – Veedrac
    Nov 19 at 5:05
















  • 1




    Can you please remove all the std::chrono stuff and std::cout from your code and try again? I made a .js file with the js code you provided and tested it and it took approximately 150ms when I tested it with (node fibjs.js). Then, I compiled the C code twice: once with the chrono stuff, once without. For the second version, I put the time-measuring code in the generated js file, before and after the run function. The first compiled version took 300+ms, but the second one took 130-150ms, so very close to the pure js code.
    – Adi
    Nov 18 at 13:17










  • So...based on my results, I guess that using a lot of libraries or complex functions also affect the compiled js code.
    – Adi
    Nov 18 at 13:18










  • @Adi Can you please guide me where to put that time-measuring code in generated fib.js file? I tried removing all the chrono stuff and putting time-measuring code in the run(args) method of the generated JS file but no difference.
    – Rajat Saxena
    Nov 18 at 13:30






  • 1




    At the end of the fib.js file, there is a call to the run function: run();; I analyzed the code and basically that is the entry point of the program. You can use a simple console.time('test'); run(); console.timeEnd('test'); to measure the time.
    – Adi
    Nov 18 at 14:01








  • 1




    You're also not building with optimizations (emcc -O3 or -Os).
    – Veedrac
    Nov 19 at 5:05










1




1




Can you please remove all the std::chrono stuff and std::cout from your code and try again? I made a .js file with the js code you provided and tested it and it took approximately 150ms when I tested it with (node fibjs.js). Then, I compiled the C code twice: once with the chrono stuff, once without. For the second version, I put the time-measuring code in the generated js file, before and after the run function. The first compiled version took 300+ms, but the second one took 130-150ms, so very close to the pure js code.
– Adi
Nov 18 at 13:17




Can you please remove all the std::chrono stuff and std::cout from your code and try again? I made a .js file with the js code you provided and tested it and it took approximately 150ms when I tested it with (node fibjs.js). Then, I compiled the C code twice: once with the chrono stuff, once without. For the second version, I put the time-measuring code in the generated js file, before and after the run function. The first compiled version took 300+ms, but the second one took 130-150ms, so very close to the pure js code.
– Adi
Nov 18 at 13:17












So...based on my results, I guess that using a lot of libraries or complex functions also affect the compiled js code.
– Adi
Nov 18 at 13:18




So...based on my results, I guess that using a lot of libraries or complex functions also affect the compiled js code.
– Adi
Nov 18 at 13:18












@Adi Can you please guide me where to put that time-measuring code in generated fib.js file? I tried removing all the chrono stuff and putting time-measuring code in the run(args) method of the generated JS file but no difference.
– Rajat Saxena
Nov 18 at 13:30




@Adi Can you please guide me where to put that time-measuring code in generated fib.js file? I tried removing all the chrono stuff and putting time-measuring code in the run(args) method of the generated JS file but no difference.
– Rajat Saxena
Nov 18 at 13:30




1




1




At the end of the fib.js file, there is a call to the run function: run();; I analyzed the code and basically that is the entry point of the program. You can use a simple console.time('test'); run(); console.timeEnd('test'); to measure the time.
– Adi
Nov 18 at 14:01






At the end of the fib.js file, there is a call to the run function: run();; I analyzed the code and basically that is the entry point of the program. You can use a simple console.time('test'); run(); console.timeEnd('test'); to measure the time.
– Adi
Nov 18 at 14:01






1




1




You're also not building with optimizations (emcc -O3 or -Os).
– Veedrac
Nov 19 at 5:05






You're also not building with optimizations (emcc -O3 or -Os).
– Veedrac
Nov 19 at 5:05



















active

oldest

votes











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














 

draft saved


draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53360895%2fwhy-is-webassembly-this-slow-as-compared-to-javascript%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown






























active

oldest

votes













active

oldest

votes









active

oldest

votes






active

oldest

votes
















 

draft saved


draft discarded



















































 


draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53360895%2fwhy-is-webassembly-this-slow-as-compared-to-javascript%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

If I really need a card on my start hand, how many mulligans make sense? [duplicate]

Alcedinidae

Can an atomic nucleus contain both particles and antiparticles? [duplicate]