Why the web worker version runs longer? - javascript

I'm trying to sum up numbers using two different variants, without web workers and using web workers.
I expect the web workers version to be about ten times faster because I divide the interval into ten intervals, but it's not like that. It's about ten times slower. I do not understand why. Does the ten web workers work in parallel?
var sum1 = 0, sum2 = 0, nrElements = 10000000;
var t0 = performance.now();
for (var i=0; i < nrElements; i++) {
sum1 += i;
}
var t1 = performance.now();
console.log("Version1 - " + (t1 - t0) + " sum: " + sum1)
var t3 = performance.now();
var n, running;
var pas = 0;
running = 0;
for (n = 0; n < 10; ++n) {
let workers = new Worker("worker.js");
pozStart = pas;
pas += nrElements / 10;
pozStop = pas;
workers.postMessage({start: pozStart, stop: pozStop});
workers.onmessage = workerDone;
++running;
}
function workerDone(e) {
--running;
sum2 += e.data[1];
if (running === 0) {
var t4 = performance.now();
console.log("Version2 - " + (t4 - t3) + " sum: " + sum2)
}
}
//worker.js
onmessage = function(e) {
var sum=0;
for(let i= e.data.start; i < e.data.stop; i++)
{
sum += i;
}
postMessage(["r",sum]);
}

There are many things here that could make your observations vary a lot, like how browsers do optimize your code (particularly for such simple for loops), but to answer the general question Why running through Web-Workers takes more time, then ...
You are running 10 workers in parallel. If your computer is not able to run ten threads concurrently, all your threads will indeed get slowed down.
As a rule of thumb, never exceed navigator.hardwareConcurrency- 1 number of concurrent Web Workers on the same page.
Initializing a WebWorker is not such a fast operation. It includes a Network request, parsing of the js file, building of the context. So initialize it once, and then ask them multiple times to do what you want.
But note that even then, you'll probably have slower results using the Workers with such a small operation. The simple operation
worker.postMessage(); // in main
self.onmessage = e => self.postMessage(); // in worker.js
worker.onmessage = e => ... // back in main
will already take place in at least 3 different event loops, since messages are received in the event loop following the one they've been sent from.
Unless you have some operations that will take seconds, offloading on worker might indeed get slower.
But even if slower, having your job offloaded in Worker allows the main thread to be free, and these 30ms will cause a drop of two frames, which could make something like an animation look jerky, so keep on using WebWorkers, but not for the speed.

Related

Node.js cluster - optimal number of workers

I have 4 cores and ran this code according to this example :
var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;
var id = 0;
if (cluster.isWorker) {
id = cluster.worker.id;
}
var iterations = 1000000000;
console.time('Function #' + id);
for (var i = 0; i < iterations; i++) {
var test = 0;
}
console.timeEnd('Function #' + id);
if (cluster.isMaster) {
// Fork workers.
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
}
With 4 fork (the code above), I got :
Function #0: 1698.801ms
Function #1: 3282.679ms
Function #4: 3290.384ms
Function #3: 3425.090ms
Function #2: 3424.922ms
With 3 fork, I got :
Function #0: 1695.155ms
Function #2: 1822.867ms
Function #3: 2444.156ms
Function #1: 2606.680ms
With 2 fork, I got :
Function #0: 1684.929ms
Function #1: 1682.897ms
Function #2: 1686.123ms
I don't understand these results. Isn't 1 fork/core the optimal number ? Here I see that 4 fork is not better than 2 fork.
My guess is that your hardware actually only has 2 physical cores. However, because of hyper-threading (HT), the OS will say that there are 4 (logical) cores present.
The workers in your code keep a (physical) core entirely occupied, which is something that HT can't deal with very well, so the performance when keeping all 4 logical cores busy will be worse than when you keep only the 2 physical cores busy.
My hardware (quad core, so 4 physical and 8 logical cores) shows the same pattern:
8 workers:
Function #5: 926ms
Function #3: 916ms
Function #1: 928ms
Function #4: 895ms
Function #7: 934ms
Function #6: 905ms
Function #8: 928ms
Function #2: 928ms
4 workers:
Function #3: 467ms
Function #2: 467ms
Function #1: 473ms
Function #4: 472ms
That said, the rule of thumb of making the number of workers equivalent to the number of logical cores in your hardware still makes sense if your workers are I/O bound (which most Node apps are).
If you really want to perform heavy, blocking, calculations, count one physical core per worker.

How Can I make millisecond Unique?

I'm using NodeJs.
I received constantly request from server.
I'm added some variable like createdTime to it and saved to the database.
when I sorted data by createdTime in some case It is not reliable, It is Repeated
How can I make differentiate between them ?
I do not want to count request.
I do not like to change timestamp's format.
var createdTime = new Date().getTime();
Here's a method of combining a counter with the current time to allow you to have as many as 1000 separate transactions within the same ms that are all uniquely numbered, but still a time-based value.
And, here's a working snippet to illustrate:
// this guarantees a unique time-based id
// as long as you don't have more than 1000
// requests in the same ms
var getTransactionID = (function() {
var lastTime, counter = 0;
return function() {
var now = Date.now();
if (now !== lastTime) {
lastTime = now;
counter = 0;
} else {
++counter;
}
return (now * 1000) + counter;
}
})();
for (var i = 0; i < 100; i++) {
document.write(getTransactionID() + "<br>");
}
If you want something that is likely to work across clusters, you can use process.hrtime() to use the high resolution timer instead of the counter and then make the id be a string that could be parsed into a relative time if needed. Since this requires node.js, I can't make a working snippet here in the browser, but here's the idea:
// this makes a unique time-based id
function getTransactionID () {
var now = Date.now();
var hrtime = process.hrtime();
return now + "." + ((hrtime[0] * 1e9) + hrtime[1]);
}
Due to my low rep I can't add a comment but it looks like you are needing to go beyond milliseconds.Maybe this stackoverflow question can help you
How to get a microtime in Node.js?

window.performance.now() equivalent in nodejs?

I think the question is straight forward.
I'm looking for something that's similar to window.performance.now() in nodejs V8 engine.
Right now I'm just using:-
var now = Date.now();
//do some processing..
console.log("time elapsed:", Date.now() - now);
But, I read that window.performance.now() is lot more accurate than using the date because of the what's defined here.
Node v8.5.0 has added Performance Timing API, which includes the performance#now(), e.g.
const {
performance
} = require('perf_hooks');
console.log('performance', performance.now());
I would only mention that three of the reasons the author gives for the preference of the timing API in the browser wouldn't seem to apply directly to a node situation, and the fourth, the inaccuracy of Javscript time, cites an article from 2008, and I would strongly caution against relying on older material regarding Javascript performance specifics, particularly given the recent round of performance improvements all the engines have made to support "HTML5" apps.
However, in answer to your question, you should look at process.hrtime()
UPDATE: The present package (available via npm install present) provides some sugar around hrtime if you'd like it.
Note: Since the version 8.5.0 of Node, you can use performance.now()
Here's a shortcut for process.hrtime() that returns milliseconds instead of microseconds:
function clock(start) {
if ( !start ) return process.hrtime();
var end = process.hrtime(start);
return Math.round((end[0]*1000) + (end[1]/1000000));
}
Usage:
var start = clock();
// do some processing that takes time
var duration = clock(start);
console.log("Took "+duration+"ms");
Will output something like "Took 200ms"
What about?
console.time('FooTimer');
// do the work
console.timeEnd('FooTimer');
process.uptime()
Official Node Documentation
"The process.uptime() method returns the number of seconds the
current Node.js process has been running.
The return value includes fractions of a second. Use Math.floor() to
get whole seconds."
Example: Measure For Loop Execution Time
const nemo = ['nemo'];
function findNemo(array) {
let start_time = process.uptime();
for (let iteration = 0; iteration < array.length; iteration++) {
if (array[iteration] === 'nemo') {
console.log("Found Nemo");
}
}
let end_time = process.uptime();
console.log("For loop took this much time: ", end_time - start_time);
}
findNemo(nemo);
Example Output
Here's a Typescript version with process.hrtime(), based on NextLocal's answer:
class Benchmark {
private start = process.hrtime();
public elapsed(): number {
const end = process.hrtime(this.start);
return Math.round((end[0] * 1000) + (end[1] / 1000000));
}
}
export = Benchmark;
Usage:
import Benchmark = require("./benchmark");
const benchmark = new Benchmark();
console.log(benchmark.elapsed());
To sum up and avoiding using perf_hooks
const performance = {
now: function(start) {
if ( !start ) return process.hrtime();
var end = process.hrtime(start);
return Math.round((end[0]*1000) + (end[1]/1000000));
}
}
console.log('performance', performance.now());
This method came into existence in version 8.5.0 of nodejs https://nodejs.org/api/perf_hooks.html#perf_hooks_performance_measurement_apis
compare solutions with and without loop.
Note down, which makes a difference performance wise ?
Try it out in JS snippets in developer tools or any JS editor.
function sum(n) {
let total = 0;
for (let i = 0; i <= n; i++) {
total += i;
}
return total;
}
var t1 = performance.now();
sum(100000000);
var t2 = performance.now();
console.log(`time elapsed: ${(t2-t1)/1000} seconds.`);
function addupto(n) {
return n * (n + 1) / 2;
}
var t3 = performance.now();
addupto(100000000);
var t4 = performance.now();
console.log(`time elapsed: ${(t4-t3)/1000} seconds.`);

Caculating function running time

I want to calculate the average running time of a function in JavaScript like this:
time = 0;
while(1000) {
time1 = performance.now();
function();
time2 = performance.now();
time += (time2-time1);
}
The problem is that only the first loop the time interval is about 60ms and the following loop the interval is nearly zero.
So I changed the code to:
time1 = performance.now();
while(1000000) {
function();
}
time2 = performance.now();
time = (time2-time1);
The running time is about 4 seconds.
I guess maybe it is because of the automatic optimisation.
If it is this case, are there any approaches to close the optimisation?
You've most likely caused the browser to hand off that code to its JIT compiler. The first run is always through the interpreter (slow). Hot code gets put through the JIT and the resulting native (fast) code is then used.
This is automatic and generally out of your hands to control. You can disable the Firefox JIT compiler by using 'with' in a script.
with({}) {}
Add this to the top of your script and the JIT will be disabled for your script.
You can also use console.time and console.endTime function to calculate the running time.
example:
console.time('profile 1');
for ( var i=0; i < 100000; i++) {
var arr = new Array();
}
console.timeEnd('profile 1');//profile 1: 108.492ms
console.time('profile 2');
for ( var i=0; i < 100000; i++) {
var arr = [];
}
console.timeEnd('profile 2');//profile 2: 81.907ms

JavaScript browser parsing speed testing

I'm looking into the speed of JavaScript parsers in web browsers, importantly it needs to be easy to demonstrate. I came up with a simple test - the idea being that each script block is parsed and executed individually, so a large block of script could be timed:
<script>var start = new Date().getTime();</script>
<script>
/*! jQuery v1.8.2 jquery.com | jquery.org/license */
...
</script>
<script>alert ( new Date().getTime() - start );</script>
Superficially this appears to work, removing the middle script block will result in a negligible time.
However I'm not certain that my logic is not fundamentally flawed.
It seems the answer is broadly yes, but to get a reasonable result (like anything else) the test should be run many times to level out the effects of compilation caching and garbage collection. The test above can easily be placed into the Parse-n-Load library: http://carlos.bueno.org/2010/02/measuring-javascript-parse-and-load.html
Thanks for your help
This may be of help!
var start = new Date().getTime();
var end = new Date().getTime();
var time = end - start;
alert('Execution time: ' + time);
If you want to benchmark your JavaScript, include MilliSeconds etc.
var t = new Date();
var start = t.getTime()*1000 + t.getMilliseconds();
/* do something*/
var t2 = new Date();
var end = t2.getTime()*1000 + t.getMilliseconds();
alert("The Code needed " + (end-start) + " milliseconds. That are " + parseInt((end-start)/1000) + " seconds.");
You might want to differentiate between parsing and execution time. You could do something like
<script>start = Date.now();</script>
<script>
parsed = Date.now();
/*! jQuery v1.8.2 jquery.com | jquery.org/license */
…
</script>
<script>var end = Date.now();
alert ( "parsed in " + (parsed - start) + "ms" );
alert ( "executed in " + (end - parsed) + "ms" );
alert ( "overall time: " + (end - start) + "ms" );
</script>
With that you might be able to detect cached parse trees etc. Yet, for more distinct information have a look at your developer tools, they show such type of information in their profiler section. Or in Opera, it's included in the load process of scripts in the network panel.
This answer is from 10 years in the future.
There are a number of approaches to timing web page processes including:
Date-related methods:
Date.now();
and:
console.time-related methods:
console.time('myTimer');
console.timeLog('myTimer');
console.timeEnd('myTimer');
but, since late 2015, the ideal way to time web page processes using high-resolution timestamps has been:
window.performance.now();
Using Performance:
The Performance interface, accessed via window.performance has numerous methods, including:
timeOrigin
mark
measure
getEntries
toJSON
and more.
But in order to time a script, all you need is window.performance.now():
let scriptStart = window.performance.now();
let scriptEnd = window.performance.now();
let scriptDuration = (scriptEnd - scriptStart);
Working Example:
let paragraph = document.querySelector('p');
let button = document.querySelector('button');
const runTimedScript = () => {
let scriptStart = window.performance.now();
for (let i = 0; i < 10000; i++) {
paragraph.textContent = 'Loop iteration ' + (i + 1);
}
let scriptEnd = window.performance.now();
let scriptDuration = (scriptEnd - scriptStart);
button.textContent = 'Re-run Script';
console.log('The script ran in ' + scriptDuration + ' milliseconds');
}
button.addEventListener('click', runTimedScript, false);
button {
cursor: pointer;
}
<p></p>
<button type="button">Run Script</button>
<p>To see how long the script takes to run,<br />
click the button above repeatedly.</p>
Further Reading:
To find out more about the Performance Interface, see:
Performance API (MDN)

Categories