Why does function b below (in Node JS) skip iterations? [duplicate] - node.js

This question already has answers here:
What is the purpose of the var keyword and when should I use it (or omit it)?
(19 answers)
Closed 2 years ago.
I was looking into how Node JS executes code. If I set the 'sleep' parameter to 1 in both functions it works as expected.
But with different delays in the two functions, it skips iterations for the function with the longest delay.
I would expect function b to log all numbers from 0 to 99 but slower than function a.
See the code in mycompiler.io
a()
b()
async function a() {
for (n=1; n<100; n++) {
console.log('a', n)
await sleep(1)
}
}
async function b() {
for (n=1; n<100; n++) {
console.log('b', n)
await sleep(3)
}
}
function sleep(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
})
}

As #CertainPerformance mentioned in the comment you must declare your variable if you want your for loops to perform correctly here. for(let n=1; n<100; n++)
Sine you're not running node in strict mode, those n variables are now essentially referencing a single shared variable, so you should notice, there are actually no numbers getting skipped, rather both functions are creating a single shared iteration from 1 to 99.
Here's what a working version of this looks like:
'use strict'
a()
b()
async function a() {
for (let n=1; n<100; n++) {
console.log('a', n)
await sleep(1)
}
}
async function b() {
for (let n=1; n<100; n++) {
console.log('b', n)
await sleep(3)
}
}
function sleep(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
})
}
To echo again what was said in the comments, had you run your script in strict mode this error would have been thrown when you ran the code:
ReferenceError: n is not defined

Related

How to prevent that event is emitted from outside?

Imagine I had a simple counting process that acts as a default Node EventEmitter:
import {EventEmitter} from 'events';
async function sleep(milliseconds: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, milliseconds));
}
class MyCountingProcess extends EventEmitter {
public async start() {
for (let i = 0; i <= 10; i++) {
this.emit('counting', i);
await sleep(1000); // just some demo async function
}
}
}
const myCountingProcess = new MyCountingProcess();
myCountingProcess.on('counting', (value) => {
console.log("current value is: " + value);
});
myCountingProcess.start();
So far, everything works as intended.
What puzzles me however is that I could very easily disturb this logic by adding another line outside MyCountingProcess (after myCountingProcess.start()) like
myCountingProcess.emit(666);
Then suddenly, the exact same process would no longer work as intended.
Is this intentional? Or bad architectural design? Or am I using the EventEmitter pattern wrong?
It would make much more sense to me if emit could only be called by the EventEmitter (i.e. within it), not on it. Or at least if it could be made a private method in TypeScript, although that would of course only be syntax.
So what would one usually do to prevent scenarios like this one?
Because MyCountingProcess is extending EventEmitter, it will behave as an EventEmmiter instance, unless you override the event methods.
For your use case, I recommend adding the EventEmmiter as a variable inside MyCountingProcess like this:
import { EventEmitter } from 'events';
class MyCountingProcess {
#events: EventEmitter
constructor() {
this.#events = new EventEmitter()
}
public async start() {
for (let i = 0; i <= 10; i++) {
this.#events.emit('counting', i);
await sleep(1000);
}
}
public on(event: string | symbol, listener: (...args: any[]) => void) {
return this.#events.on(event, listener)
}
}
const myCountingProcess = new MyCountingProcess();
myCountingProcess.on('counting', (value) => {
console.log("current value is: " + value);
});
myCountingProcess.start();

Why is the first function call is executed two times faster than all other sequential calls?

I have a custom JS iterator implementation and code for measuring performance of the latter implementation:
const ITERATION_END = Symbol('ITERATION_END');
const arrayIterator = (array) => {
let index = 0;
return {
hasValue: true,
next() {
if (index >= array.length) {
this.hasValue = false;
return ITERATION_END;
}
return array[index++];
},
};
};
const customIterator = (valueGetter) => {
return {
hasValue: true,
next() {
const nextValue = valueGetter();
if (nextValue === ITERATION_END) {
this.hasValue = false;
return ITERATION_END;
}
return nextValue;
},
};
};
const map = (iterator, selector) => customIterator(() => {
const value = iterator.next();
return value === ITERATION_END ? value : selector(value);
});
const filter = (iterator, predicate) => customIterator(() => {
if (!iterator.hasValue) {
return ITERATION_END;
}
let currentValue = iterator.next();
while (iterator.hasValue && currentValue !== ITERATION_END && !predicate(currentValue)) {
currentValue = iterator.next();
}
return currentValue;
});
const toArray = (iterator) => {
const array = [];
while (iterator.hasValue) {
const value = iterator.next();
if (value !== ITERATION_END) {
array.push(value);
}
}
return array;
};
const test = (fn, iterations) => {
const times = [];
for (let i = 0; i < iterations; i++) {
const start = performance.now();
fn();
times.push(performance.now() - start);
}
console.log(times);
console.log(times.reduce((sum, x) => sum + x, 0) / times.length);
}
const createData = () => Array.from({ length: 9000000 }, (_, i) => i + 1);
const testIterator = (data) => () => toArray(map(filter(arrayIterator(data), x => x % 2 === 0), x => x * 2))
test(testIterator(createData()), 10);
The output of the test function is very weird and unexpected - the first test run is constantly executed two times faster than all the other runs. One of the results, where the array contains all execution times and the number is the mean (I ran it on Node):
[
147.9088459983468,
396.3472499996424,
374.82447600364685,
367.74555300176144,
363.6300039961934,
362.44370299577713,
363.8418449983001,
390.86111199855804,
360.23125199973583,
358.4788999930024
]
348.6312940984964
Similar results can be observed using Deno runtime, however I could not reproduce this behaviour on other JS engines. What can be the reason behind it on the V8?
Environment:
Node v13.8.0, V8 v7.9.317.25-node.28,
Deno v1.3.3, V8 v8.6.334
(V8 developer here.) In short: it's inlining, or lack thereof, as decided by engine heuristics.
For an optimizing compiler, inlining a called function can have significant benefits (e.g.: avoids the call overhead, sometimes makes constant folding possible, or elimination of duplicate computations, sometimes even creates new opportunities for additional inlining), but comes at a cost: it makes the compilation itself slower, and it increases the risk of having to throw away the optimized code ("deoptimize") later due to some assumption that turns out not to hold. Inlining nothing would waste performance, inlining everything would waste performance, inlining exactly the right functions would require being able to predict the future behavior of the program, which is obviously impossible. So compilers use heuristics.
V8's optimizing compiler currently has a heuristic to inline functions only if it was always the same function that was called at a particular place. In this case, that's the case for the first iterations. Subsequent iterations then create new closures as callbacks, which from V8's point of view are new functions, so they don't get inlined. (V8 actually knows some advanced tricks that allow it to de-duplicate function instances coming from the same source in some cases and inline them anyway; but in this case those are not applicable [I'm not sure why]).
So in the first iteration, everything (including x => x % 2 === 0 and x => x * 2) gets inlined into toArray. From the second iteration onwards, that's no longer the case, and instead the generated code performs actual function calls.
That's probably fine; I would guess that in most real applications, the difference is barely measurable. (Reduced test cases tend to make such differences stand out more; but changing the design of a larger app based on observations made on a small test is often not the most impactful way to spend your time, and at worst can make things worse.)
Also, hand-optimizing code for engines/compilers is a difficult balance. I would generally recommend not to do that (because engines improve over time, and it really is their job to make your code fast); on the other hand, there clearly is more efficient code and less efficient code, and for maximum overall efficiency, everyone involved needs to do their part, i.e. you might as well make the engine's job simpler when you can.
If you do want to fine-tune performance of this, you can do so by separating code and data, thereby making sure that always the same functions get called. For example like this modified version of your code:
const ITERATION_END = Symbol('ITERATION_END');
class ArrayIterator {
constructor(array) {
this.array = array;
this.index = 0;
}
next() {
if (this.index >= this.array.length) return ITERATION_END;
return this.array[this.index++];
}
}
function arrayIterator(array) {
return new ArrayIterator(array);
}
class MapIterator {
constructor(source, modifier) {
this.source = source;
this.modifier = modifier;
}
next() {
const value = this.source.next();
return value === ITERATION_END ? value : this.modifier(value);
}
}
function map(iterator, selector) {
return new MapIterator(iterator, selector);
}
class FilterIterator {
constructor(source, predicate) {
this.source = source;
this.predicate = predicate;
}
next() {
let value = this.source.next();
while (value !== ITERATION_END && !this.predicate(value)) {
value = this.source.next();
}
return value;
}
}
function filter(iterator, predicate) {
return new FilterIterator(iterator, predicate);
}
function toArray(iterator) {
const array = [];
let value;
while ((value = iterator.next()) !== ITERATION_END) {
array.push(value);
}
return array;
}
function test(fn, iterations) {
for (let i = 0; i < iterations; i++) {
const start = performance.now();
fn();
console.log(performance.now() - start);
}
}
function createData() {
return Array.from({ length: 9000000 }, (_, i) => i + 1);
};
function even(x) { return x % 2 === 0; }
function double(x) { return x * 2; }
function testIterator(data) {
return function main() {
return toArray(map(filter(arrayIterator(data), even), double));
};
}
test(testIterator(createData()), 10);
Observe how there are no more dynamically created functions on the hot path, and the "public interface" (i.e. the way arrayIterator, map, filter, and toArray compose) is exactly the same as before, only under-the-hood details have changed. A benefit of giving all functions names is that you get more useful profiling output ;-)
Astute readers will notice that this modification only shifts the issue away: if you have several places in your code that call map and filter with different modifiers/predicates, then the inlineability issue will come up again. As I said above: microbenchmarks tend to be misleading, as real apps typically have different behavior...
(FWIW, this is pretty much the same effect as at Why is the execution time of this function call changing? .)
Just to add to this investigation, I compared the OP's original code with the predicate and selector functions declared as separate functions as suggested by jmrk to two other implementations. So, this code has three implementations:
OP's code with predicate and selector functions declared separately as named functions (not inline).
Using standard array.map() and .filter() (which you would think would be slower because of the extra creation of intermediate arrays)
Using a custom iteration that does both filtering and mapping in one iteration
The OP's attempt at saving time and making things faster is actually the slowest (on average). The custom iteration is the fastest.
I guess the lesson here is that it's not necessarily intuitive how you make things faster with the optimizing compiler so if you're tuning performance, you have to measure against the "typical" way of doing things (which may benefit from the most optimizations).
Also, note that in the method #3, the first two iterations are the slowest and then it gets faster - the opposite effect from the original code. Go figure.
The results are here:
[
99.90320014953613,
253.79690098762512,
271.3091011047363,
247.94990015029907,
247.457200050354,
261.9487009048462,
252.95090007781982,
250.8520998954773,
270.42809987068176,
249.340900182724
]
240.59370033740998
[
222.14270091056824,
220.48679995536804,
224.24630093574524,
237.07260012626648,
218.47070002555847,
218.1493010520935,
221.50559997558594,
223.3587999343872,
231.1618001461029,
243.55419993400574
]
226.01488029956818
[
147.81360006332397,
144.57479882240295,
73.13350009918213,
79.41700005531311,
77.38950109481812,
78.40880012512207,
112.31539988517761,
80.87990117073059,
76.7899010181427,
79.79679894447327
]
95.05192012786866
The code is here:
const { performance } = require('perf_hooks');
const ITERATION_END = Symbol('ITERATION_END');
const arrayIterator = (array) => {
let index = 0;
return {
hasValue: true,
next() {
if (index >= array.length) {
this.hasValue = false;
return ITERATION_END;
}
return array[index++];
},
};
};
const customIterator = (valueGetter) => {
return {
hasValue: true,
next() {
const nextValue = valueGetter();
if (nextValue === ITERATION_END) {
this.hasValue = false;
return ITERATION_END;
}
return nextValue;
},
};
};
const map = (iterator, selector) => customIterator(() => {
const value = iterator.next();
return value === ITERATION_END ? value : selector(value);
});
const filter = (iterator, predicate) => customIterator(() => {
if (!iterator.hasValue) {
return ITERATION_END;
}
let currentValue = iterator.next();
while (iterator.hasValue && currentValue !== ITERATION_END && !predicate(currentValue)) {
currentValue = iterator.next();
}
return currentValue;
});
const toArray = (iterator) => {
const array = [];
while (iterator.hasValue) {
const value = iterator.next();
if (value !== ITERATION_END) {
array.push(value);
}
}
return array;
};
const test = (fn, iterations) => {
const times = [];
let result;
for (let i = 0; i < iterations; i++) {
const start = performance.now();
result = fn();
times.push(performance.now() - start);
}
console.log(times);
console.log(times.reduce((sum, x) => sum + x, 0) / times.length);
return result;
}
const createData = () => Array.from({ length: 9000000 }, (_, i) => i + 1);
const cache = createData();
const comp1 = x => x % 2 === 0;
const comp2 = x => x * 2;
const testIterator = (data) => () => toArray(map(filter(arrayIterator(data), comp1), comp2))
// regular array filter and map
const testIterator2 = (data) => () => data.filter(comp1).map(comp2);
// combine filter and map in same operation
const testIterator3 = (data) => () => {
let result = [];
for (let value of data) {
if (comp1(value)) {
result.push(comp2(value));
}
}
return result;
}
const a = test(testIterator(cache), 10);
const b = test(testIterator2(cache), 10);
const c = test(testIterator3(cache), 10);
function compareArrays(a1, a2) {
if (a1.length !== a2.length) return false;
for (let [i, val] of a1.entries()) {
if (a2[i] !== val) return false;
}
return true;
}
console.log(a.length);
console.log(compareArrays(a, b));
console.log(compareArrays(a, c));

How do I return value from inner function without creating chain of return?

function xyz() {
function abc() {
function haha() {
return 5;
}
return haha();
}
return abc();
}
console.log(xyz());
I get '5' in console. Thats ok. Its a simple code of larger problem where there is lots of nested functions. I dont want to return one after the other. Is there any way, I can return from any function and return it to original function caller.
function xyz() {
function abc() {
return 5;
}
return abc()
}
console.log(xyz());
ok maybe you need call backs. I don't get the context of what you are trying to do but I'll just try.
function logTheAnswer (a) {
console.log(a)
}
function add(a, b, cb) {
cb(a + b)
}
add(1,2,logTheAnswer)
now you can nest the call backs indefinitely though try to keep it a minimum as you will experience call back hell.
Sorry to say but your question is a bit confusing without a proper output representation. But you can use callback functions with which you can easily manage your nested calls and returns.
function myFunc3(a, b, callback3){
callback3(a+b);
}
function myFunc2(a, b, c, callback2){
myFunc3(a+c, b, function(result2){
callback2(result2);
})
}
function myFunc1(){
myFunc2(a,b,c, function(result1){
console.log(result1);
})
}
Add a return the from abc function call
function xyz() {
function abc() {
return 5;
}
return abc();
}
console.log(xyz());
Or return an IIFE (Immediately Invoked Function Expression)
function xyz() {
return (function abc() {
return 5;
})();
}
console.log(xyz())

How to Create a function in Node.js

I am using Firebase function to create an API and at the same time I Am using the Firebase Firestore as my database.
I am using Node.js to create the program.
I wanted to know how to create a function in Node.js.
I will be calling a code more than once and since I have been use to Java and Java has molecularity will it be possible in Node.js also?
This is my code
exports.new_user = functions.https.onRequest((req, res) => {
var abc=``;
if(a=='true')
{
abc=Function_A();//Get the results of Function A
}
else
{
abc=Function_B();//Get the results of Function B
//Then Call Function A
}
});
As shown in the code I would be calling the same function two times from different location depending upon the situation and then utilizing the result of it.
Is it possible to declare a function and then call if from different locations and then utilize its result?
Any help would be really appreciated as I am new to Node.js
If you are trying to just get a value back from the function it depends if you are doing synchronous (adding 2 numbers together) or asynchronous (doing an HTTP call)
synchronous:
let abc = 0;
if(a=='true')
{
abc = Function_A();//Get the results of Function A
}
else
{
abc = Function_B();//Get the results of Function B
//Then Call Function A
}
function Function_B() {
return 2+2;
}
function Function_A() {
return 1+1;
}
asynchronous:
let abc = 0;
if(a=='true')
{
Function_A(function(result) {
abc = result;
});//Get the results of Function A
}
else
{
Function_A(function(result) {
abc = result;
});//Get the results of Function A
}
function Function_B(callback) {
callback(2+2);
}
function Function_A(callback) {
callback(1+1);
}
Asynchronous with variable:
let abc = 0;
Function_A(2, function(result) {
abc = result; //should by 4
});//Get the results of Function A
function Function_A(myVar, callback) {
callback(myVar * 2);
}

turning a synchronous function into asynchronous function

I have a for loop which does many iterations .I would like to put that piece of code in a custom async function as it is blocking.Is there anyway I can write a function so it will call a callback once the loop iteration is over?.
Use asynchronous-function-inside-a-loop paradigm. This ensures that the asynchronous functions get called with the correct value of the index variable.
var total = someObject.list.length;
var count = 0;
for(var i = 0; i < total; i++){
(function(foo){
myobj.get(someObject.list[foo], function(err, response) {
do_something(foo);
count++;
if (count > total - 1) done();
});
}(i)); //To immediately invoke the function passing 'i' as parameter
}
function done() {
console.log('All data loaded');
}

Resources