Re: [nodejs] Anonymous functions garbage collection

255 views
Skip to first unread message

Vinayak Mishra

unread,
Sep 13, 2012, 8:33:50 AM9/13/12
to nod...@googlegroups.com
I don't see any problem with your approach, and I would probably have done the same. Yet, JSLint would remind about making functions within loop. Well, should not matter unless you're looping over arrays with some thousands elements.

As an alternative, if code readability/simplicity is a concern, why not go with async?

var execute = function (item, cb) {
  /* do something meaningful with item, fire cb when done */
  };

var arr = getInitialData();
async.forEach(arr, execute, function (err) {
  // check for error and/or proceed further
});

You could use one of many available control flows, check out many more control flows. The advantage is the package provides different control flows without having to keep re-inventing them. Say, you want to perform certain activity in parallel, or in series, or based on some conditionals, while we could write code to achieve that, I would recommend using async as it is well written and thoroughly tested piece of code.

Where you want to place the execute code depends on many factors, like do we need to access/modify other variables in scope, if independent operations, they can go in library functions.

Please share your thoughts.


On 09/13/2012 11:30 AM, Maxim Kazantsev wrote:
It is a pretty typical approach to use an anonymous function for asynchronous calls from inside a loop:

var a = getInitialData();
for (var i = 0, len = a.length; i < len; i++) {
  (function(el) {
    /* do something non-blocking here */
  })(a[i]);
}

JSLint doesn't like this code with "Don't make functions within a loop" warning, and it is actually right since it really creates a new anonymous function on every single loop iteration. An obvious solution is to declare this function outside a loop, but it would make a code less readable. Even if a declaration would just precede the loop: you see a call here, you see a declaration somewhere else, and here you are, lost all your attention.

My question is how bad this approach is for an overall performance? In particular, how fast and efficient a garbage collection of anonymous functions is? How much memory a typical anonymous function can consume and how long it may exist in a memory?
--
Job Board: http://jobs.nodejs.org/
Posting guidelines: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
You received this message because you are subscribed to the Google
Groups "nodejs" group.
To post to this group, send email to nod...@googlegroups.com
To unsubscribe from this group, send email to
nodejs+un...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/nodejs?hl=en?hl=en

-- 
Regards,
Vinayak

greelgorke

unread,
Sep 13, 2012, 10:54:01 AM9/13/12
to nod...@googlegroups.com
well. you have to understand why this is done in this way. the immediate function is used here to create scope, so every closure created has access to the right value. w/o this construct every of all a.lenght clojures will acces the same value: a[a.length-1].

i do not agree that defining a function somewhere else decrease readability, its the opposite. if i declare well named, pure function i increase readability, plus, reusability, reduce my memory footprint and garbage collection effort.

Jorge

unread,
Sep 13, 2012, 11:26:21 AM9/13/12
to nod...@googlegroups.com
On 13/09/2012, at 08:00, Maxim Kazantsev wrote:

> It is a pretty typical approach to use an anonymous function for asynchronous calls from inside a loop:
>
> var a = getInitialData();
> for (var i = 0, len = a.length; i < len; i++) {
> (function(el) {
> /* do something non-blocking here */
> })(a[i]);
> }
>
> JSLint doesn't like this code with "Don't make functions within a loop" warning, and it is actually right since it really creates a new anonymous function on every single loop iteration. An obvious solution is to declare this function outside a loop, but it would make a code less readable.

Come on!

> Even if a declaration would just precede the loop: you see a call here, you see a declaration somewhere else, and here you are, lost all your attention.

Perhaps. Or perhaps not. If you give the inner function a good name it will help understand what's going on there.

> My question is how bad this approach is for an overall performance?

Well, even though this:

function ƒ (i) { ctr+= i }
while (i--) ƒ(i);

is twice as fast as this:

while (i--) (function (i) { ctr+= i })(i);

<https://gist.github.com/3714498>

$ node test.js
(function (i) { ctr+= i })(i) -> 39.74ns
ƒ(i) -> 18.99ns

the difference is tiny, only 20 nano seconds!

> In particular, how fast and efficient a garbage collection of anonymous functions is? How much memory a typical anonymous function can consume and how long it may exist in a memory?

I wouldn't bother too much about these things either. Simply follow Crock's advice and declare ƒ outside of the loop. Or don't, it should just work in any case.
--
Jorge.
Message has been deleted

P. Douglas Reeder

unread,
Sep 13, 2012, 2:13:40 PM9/13/12
to nod...@googlegroups.com
Take advantage of function hoisting and make the code more readable:

var a = getInitialData(), I, len;
for (i=0, len=a.length; i<len; i++) {
    doSomething(a[i]);
}

function doSomething(el){
}

dhruvbird

unread,
Sep 14, 2012, 2:30:30 PM9/14/12
to nod...@googlegroups.com
Hello Maxim,

The real reason jslint gives you a warning is if you were to use the loop variable "i" within the function in the closure, you would always get the value of i to be a.length (assuming that the function isn't evaluated synchronously and that you don't have another function declared within the first one).

The code as you have shown seems to be perfectly safe to use though.

I wouldn't worry too much about the performance unless you profile it and determine it to be a bottleneck.

Regards,
-Dhruv.


On Thursday, September 13, 2012 2:00:42 AM UTC-4, Maxim Kazantsev wrote:
It is a pretty typical approach to use an anonymous function for asynchronous calls from inside a loop:

var a = getInitialData();
for (var i = 0, len = a.length; i < len; i++) {
  (function(el) {
    /* do something non-blocking here */
  })(a[i]);
}

JSLint doesn't like this code with "Don't make functions within a loop" warning, and it is actually right since it really creates a new anonymous function on every single loop iteration. An obvious solution is to declare this function outside a loop, but it would make a code less readable. Even if a declaration would just precede the loop: you see a call here, you see a declaration somewhere else, and here you are, lost all your attention.

My question is how bad this approach is for an overall performance? In particular, how fast and efficient a garbage collection of anonymous functions is? How much memory a typical anonymous function can consume and how long it may exist in a memory?

Shripad K

unread,
Sep 14, 2012, 3:42:18 PM9/14/12
to nod...@googlegroups.com
Why not use recursive functions?

var a = getInitialData();

function doSomething(el, i) {
   if(i < a.length) {
        /* do something non-blocking here*/
       doSomething(a[i+1], i+1);
   }
}

doSomething(a[0], 0);

--

Stewart Mckinney

unread,
Sep 14, 2012, 9:52:56 PM9/14/12
to nod...@googlegroups.com
I'm not really sure that the "define outside of loop" form is actually less readable, but I have a suspicion that Crankshaft ( V8's optimizing pipeline ) would notice that you are redefining/executing the same function in the loop ( since there is no branch statement ) and optimize the definition out of the loop.

Would be nice to get some benchmarks to confirm that though. I would probably define the method outside anyway because personally I find that more readable - its easier for me to read "doTask()" in a loop. 
Reply all
Reply to author
Forward
0 new messages