Caching array length property

Showing 1-20 of 20 messages
Caching array length property Skilldrick 2/18/11 7:04 AM
Hi all

This is something I've come across a lot, and I was wondering people's views on it.

When I'm looping through an array I generally do either this:

var arr = [1, 2, 3, 4];
for (var i = 0; i < arr.length; i++) {
  console.log(arr[i]);
}

or this:

for (var i = 0, len = arr.length; i < len; i++) {
  console.log(arr[i]);
}


I generally choose between these two depending on how many times I'm expecting the loop to run. If I think it's going to be negligible, I'll generally go for the former, just because I think it reads better.

Whenever I show anyone code like this though, they say "you should cache the length property - you're looking it up on each iteration". So, what do you guys think? To me, the second option smacks of premature optimisation.

Re: [JSMentors] Caching array length property Mark McDonnell 2/18/11 7:12 AM
Have a read of this http://blog.getify.com/2011/02/pre-maturely-optimize-revisited/ by @Getify where he talks about 'im/mature' optimisation and his thoughts on this discussion.

Personally, I think that it's such a minor tweak that I will always cache the array length. Why wouldn't you? It doesn't make the code un-readable, it's obvious to any level developer what's happening (i.e. it's not some of the more cryptic 'micro-optimisations' that you can see sometimes), and it does have a testable impact on performance if you don't do it. So (to me) it seems like an easy choice to just go with caching the length.

Kind regards,
Mark 

--
To view archived discussions from the original JSMentors Mailman list: http://www.mail-archive.com/jsmentors@jsmentors.com/
 
To search via a non-Google archive, visit here: http://www.mail-archive.com/jsmentors@googlegroups.com/
 
To unsubscribe from this group, send email to
jsmentors+...@googlegroups.com

Re: [JSMentors] Caching array length property Skilldrick 2/18/11 7:36 AM

On 18 February 2011 15:12, Mark McDonnell <storm...@gmail.com> wrote:
Have a read of this http://blog.getify.com/2011/02/pre-maturely-optimize-revisited/ by @Getify where he talks about 'im/mature' optimisation and his thoughts on this discussion.

Personally, I think that it's such a minor tweak that I will always cache the array length. Why wouldn't you? It doesn't make the code un-readable, it's obvious to any level developer what's happening (i.e. it's not some of the more cryptic 'micro-optimisations' that you can see sometimes), and it does have a testable impact on performance if you don't do it. So (to me) it seems like an easy choice to just go with caching the length.

Kind regards,
Mark 


Thanks Mark, all good points, and a good read. However, in that blog, he does specifically say:

Also, notice: I am not focusing on esoteric and minute micro-performance details (as some do, and many assumed I was). I made no mention of things like array.push() vs. array[array.length], or str += "..." vs. str = arr.join(), or ++i vs. i++, or for (i=0; i < arr.length; i++) {...}vs. for (i=0, len=arr.length; i<len; i++) {...}, etc etc etc.



My feeling is that it does reduce the readability slightly, and I'm not sure whether that's worth it when i *know* it's not going to affect performance. 

Then again, if I got used to using it consistently, the readability issue wouldn't be so big a deal.

--
Nick Morgan

Re: Caching array length property Maximilian Antoni 2/18/11 7:46 AM
If you are interested in some numbers, have a look here:
http://blogs.sun.com/greimer/entry/best_way_to_code_a

Maybe that helps deciding whether you think it's worth the
optimization.

- Max
Re: Caching array length property Michael Haufe (TNO) 2/18/11 7:48 AM
On small arrays it is irrelevant, on larger ones where the length is
greater than 5000 or so it can become noticeable.

var a = [];
a[100000] = "foo";

var d1 = new Date();
for(var i=0; i < a.length; i++);
WScript.Echo(new Date() - d1 + "ms");   //34ms

d1 = new Date();
for(var j=0, len = a.length; j < len; j++);
WScript.Echo(new Date() - d1 + "ms");  //23ms

Since the arrays have to be rather large, probably better to stick
with:

arr.forEach(...)

for functional goodness.
> @skilldrick <http://twitter.com/skilldrick>
Re: [JSMentors] Caching array length property Mark McDonnell 2/18/11 7:54 AM
As far as readability is concerned I personally don't find it confusing or any harder to read, but like you say, the more you use the syntax the more accommodating it appears.

Also, as per any discussions on performance, caching the length of an array may not seem like a big time save until you have a massive array to loop through (or maybe a 'live' DOM HTMLCollection). If you know your array is only a few items long then sure not caching the length is no great shakes, but for something that effectively adds maybe 5 or so extra characters worth of typing could save you processes then I'm all up for that. 

What I don't dig is any time you have to make massive changes to how your code is architected when it only improves performance by a tiny margin - array length caching is a 1 second tweak so I see it as a something very feasible/affordable in a project.

Anyhoo, this will likely spark more back and forth discussion I'm sure :)

Kind regards,
Mark

--
To view archived discussions from the original JSMentors Mailman list: http://www.mail-archive.com/jsmentors@jsmentors.com/
 
To search via a non-Google archive, visit here: http://www.mail-archive.com/jsmentors@googlegroups.com/
 
To unsubscribe from this group, send email to
jsmentors+...@googlegroups.com

Re: [JSMentors] Caching array length property Peter van der Zee 2/18/11 8:00 AM
On Fri, Feb 18, 2011 at 4:04 PM, Nick Morgan <skill...@gmail.com> wrote:

Whenever I show anyone code like this though, they say "you should cache the length property - you're looking it up on each iteration". So, what do you guys think? To me, the second option smacks of premature optimisation.

The only real perf-wise reason to cache the length of the array you're iterating is for a live-query such as dom queries. For regular arrays, it really just is not worth the extra variable. 

Obviously the same goes for something like jquery's $foo.size(); or worse, $('#foo').size(). I'm only talking about the length of the array being iterated. But that should go without sayin...

I hate it when people say "you should cache arr.length because it's faster". While technically maybe true, it's just bullshit. But maybe that's just me ;)

- peter
Re: [JSMentors] Caching array length property galambalazs 2/18/11 8:11 AM
On Fri, Feb 18, 2011 at 4:04 PM, Nick Morgan <skill...@gmail.com> wrote:
> Hi all
> This is something I've come across a lot, and I was wondering people's views
> on it.
> When I'm looping through an array I generally do either this:
> var arr = [1, 2, 3, 4];
> for (var i = 0; i < arr.length; i++) {
>   console.log(arr[i]);
> }
> or this:
> for (var i = 0, len = arr.length; i < len; i++) {
>   console.log(arr[i]);
> }
>

Both are readable. As for the typing you can use snippets. If the
order doesn't matter you can even write:

| for (var i = arr.length; i--;) {
|   console.log(arr[i]);
| }

This is my personal favourite iteration. Small, fast, readable.

- Balázs

Re: Caching array length property Angus Croll 2/18/11 9:46 AM
Yeah, as your examples show,  the cost of not caching array length is almost always neglible. Developers should just use common sense and cache the length for massive arrays only - knee-jerk micro-optimization strategies are often the enemy of readability

BTW forEach carries its own performance issues (potentially more serious) with large arrays since every iteration is a function call


Re: [JSMentors] Caching array length property Michael Geary 2/18/11 9:49 AM
On Fri, Feb 18, 2011 at 8:00 AM, Peter van der Zee <jsme...@qfox.nl> wrote:
The only real perf-wise reason to cache the length of the array you're iterating is for a live-query such as dom queries. For regular arrays, it really just is not worth the extra variable.

That's much too general a statement. With a large enough array of any kind, it makes a difference. A case in point is my PolyGonzo project, which loops through polygon arrays with tens of thousands of points.

In PolyGonzo I took one more step and stopped checking the length entirely, using loops like this:

    for( var element, i = -1;  element = array[++i]; ) {
    }

That made a small but noticeable difference too.

This loop form works because the arrays I'm working with are known to have no null/false/undefined values. I believe it's the fastest way to loop forward through an array of that nature.

If you repeat something enough times, small improvements can add up. :-)

Obviously the same goes for something like jquery's $foo.size(); or worse, $('#foo').size(). I'm only talking about the length of the array being iterated. But that should go without sayin...

jQuery's .size() method should never be used at all. It's a relic from the very first versions of jQuery where the jQuery object was not an array-like object with a .length property.

Instead of .size(), use the .length property.

-Mike
Re: [JSMentors] Caching array length property Miller Medeiros 2/19/11 1:30 AM
I use reverse while loops always as I can (when the loop order doesn't make difference) since I find it clearer and easier to write (for loops are too verbose and cryptic in my opinion) and it usually performs better as well - you gain by caching array.length and also by looping backwards...

var n = arr.length;
while(n--){
  console.log(arr[n]);
}

for live node collections caching the length property makes a huge difference as Peter said (or if the property is actually a getter), in other cases performance shouldn't make that much difference and in some cases there is not even a real gain in performance (specially on the newest engines) if you doubt it check this test: http://jsperf.com/fun-with-for-loops

I find it a good practice to always cache the length not because of performance gains (that many times are null) but just so you get used to it and then later don't commit the mistake of not caching the length of a live collection (sometimes it isn't that clear you are dealing with a live collection and/or a getter).

PS: backwards loops are usually faster since the comparison is against zero.
PS2: if JS engines keep improving at the current pace in a close future calling methods will have very little overhead if compared to inline code - http://jsperf.com/function-call-overhead
PS3: 50% slower than speed of sound is still fast, be pragmatic.
Re: [JSMentors] Caching array length property Stefan Weiss 2/19/11 2:22 AM
On 18/02/11 17:00, Peter van der Zee wrote:
> The *only* real perf-wise *reason to cache* the length of the array you're
> iterating *is* for a *live-query* such as dom queries. For regular arrays,

> it really just is not worth the extra variable.
...
> I hate it when people say "you should cache arr.length because it's faster".
> While technically maybe true, it's just bullshit. But maybe that's just me
> ;)

No, it's not just bullshit. In one of the projects I was working on a
few years ago, this optimization did not only lead to a measurable
improvement in performance, but a reduction in UI lag which was
noticable by the users. In our case, caching the .length mattered, because

  - the users were running IE6 (not my choice, of course)
  - the hardware was not top-of-the-line
  - the arrays were large (thousands to tens of thousands of elements)
  - the pages were already very heavy, which tends to slow everything
    down in IE, so you're grateful for any small speed improvement

It really depends on your environment whether optimizations like this
make sense. If you're not sure of the impact, caching the .length might
not help, but it can't hurt either. In a library, do the safe thing and
cache it.

That said, for arrays of < 100 elements or so, it's not going to make
much of a difference. In these cases, and especially when the code is
unlikely to be run more than once, and when the "array" is not actually
a collection of DOM nodes, I sometimes also choose the slightly more
readable (IMHO) variant where arr.length is checked on each iteration.


stefan


--
LOAD"Ph'nglui mglw'nafh Cthulhu R'lyeh wgah'nagl fhtagn!",8,1
RUN!

Re: Caching array length property Angus Croll 2/19/11 6:38 AM

>>PS2: if JS engines keep improving at the current pace in a close future
calling methods will have very little overhead if compared to inline
code -
http://jsperf.com/function-call-overhead

Sadly the promise of 'near future' does not apply to those burdened
with supporting enterprises running on IE6 (thankfully not me anymore
but believe me they are still out there) I can attest that when IE is
slow every method call counts - and using regular for loops instead of
(library supplied) forEach was a significant help.

PS3: 50% slower than speed of sound is still fast, be pragmatic.

see above :-)

It's all about making informed judgements based on your own situation
- less about 'do this', 'don't do this' - which is why this group is
so great.
> calling methods will have very little overhead if compared to inline code -http://jsperf.com/function-call-overhead
Re: Caching array length property getify 2/19/11 7:46 AM
It's true that on many of the most modern browsers, purely caching the
array length for a single for-loop won't show much difference. That's
because that used to be such a problem perf-wise, and the engines
figured out specific optimizations to address it.

As has been pointed out in the previous messages, older browsers show
off these problems in glaring detail. Some people feel like you should
always write code based on the current generation browsers, others
feel you should write to what's coming "next", and others are forced
to write code that is aware of and as tolerant as possible in the
older generations of browsers.

I'd say that's more the key when deciding on these types of "micro"
optimizations... which is the least-capable engine that you care about
your code running well in. If that's bleeding edge Chrome 11, and you
don't care about the rest, then by all means, write all the un-
optimized, abstracted, layered, object-oriented code you can possibly
imagine. If you care about IE6, you might want to consider backing off
of some of that idealism and making some small sacrifices in
readability to get huge gains in performance.

The other thing that people should realize is that, with respect to
array.length caching, sometimes it's not the property lookup that's
the bottleneck, but it's that the array variable you're iterating on
is not in the current scope. If it has to do a lookup on the prototype
chain of some object and make several hops before it finds the array,
or it has to look up several levels of closure scope, or even if it
has to traverse a deeply nested object property tree, those things can
be a lot more costly (sometimes in invisible ways) than just looking
at the .length property itself. Declaring a local alias to the array
before the loop and using that can sometimes net you 8-15% better
performance on the loop. Sure, that's 15% of 3ms (aka, really small),
but it's still a gain nonetheless. It's up to you if that tiny gain is
useful. And yes, I know that some newer (not-yet-released) browsers
are getting even better about caching these lookups.

--------
Lastly, with respect to both my Script Junkie article, and my follow
up blog post (linked above), I was intentionally trying to *not*
discuss micro-optimizations like operators and .length lookups. Not
that this isn't a valid subject to be aware of, but it also doesn't
hold very much real-world improvements... mostly theoretical stuff,
like how in CS classes we got happy when we got an algorithm that was
O(n*log n) instead of O(n^2).

My articles are trying to focus on patterns of degraded performance.
They're called patterns for a reason... because they tend to repeat
themselves across your entire code base. If you are in the habit of
being sloppy about function-call overhead in your API design, or scope
lookups on nested namespaces, or things like that, this pattern will
tend to slow down most if not all of your code.

So while someone can claim looking at a single loop's performance is
just micro/premature optimization, and 20% savings on 3ms is nothing
to care about, if that same type of mistake is made across ALL your
code, and your entire program takes say 500ms to run, then 20% savings
(100ms) across the whole program is something to care about.

I think the debate over performance should shift from focusing on a
single loop or mistake to looking at patterns for bad performance that
permeate our entire code base. That's where the %'s will actually
start to pay off.

--Kyle
Re: [JSMentors] Caching array length property Angus Croll 2/19/11 9:58 AM
Ok since you mentioned favourites - I couldn't resist. Here is my world of for loop favourites :-)

http://javascriptweblog.wordpress.com/2010/10/11/rethinking-javascript-for-loops/
Re: Caching array length property bytespider 2/18/11 8:35 AM
I'll be honest I tend to do the latter for out of habit, and I agree
with Mark it's no more difficult to read.

var arr = [1, 2, 3, 4];
for (var i = 0, length = arr.length; i < length; ++i) {
  console.log(arr[i]);
}

It does benefit from being slightly more performant for large
iterations, but at the end of the day we should write the code that
feels the most natural to us. Note I also use ++i over i++ because
it's slightly faster on some modern browsers but mostly out of habit.

Rob

On Feb 18, 3:54 pm, Mark McDonnell <storm.m...@gmail.com> wrote:
> As far as readability is concerned I personally don't find it confusing or
> any harder to read, but like you say, the more you use the syntax the more
> accommodating it appears.
>
> Also, as per any discussions on performance, caching the length of an array
> may not seem like a big time save until you have a massive array to loop
> through (or maybe a 'live' DOM HTMLCollection). If you know your array is
> only a few items long then sure not caching the length is no great shakes,
> but for something that effectively adds maybe 5 or so extra characters worth
> of typing could save you processes then I'm all up for that.
>
> What I don't dig is any time you have to make massive changes to how your
> code is architected when it only improves performance by a tiny margin -
> array length caching is a 1 second tweak so I see it as a something very
> feasible/affordable in a project.
>
> Anyhoo, this will likely spark more back and forth discussion I'm sure :)
>
> Kind regards,
> Mark
>
> On 18 February 2011 15:36, Nick Morgan <skilldr...@gmail.com> wrote:
>
>
>
>
>
>
>
>
>
> > On 18 February 2011 15:12, Mark McDonnell <storm.m...@gmail.com> wrote:
>
> >> Have a read of this
> >>http://blog.getify.com/2011/02/pre-maturely-optimize-revisited/by
> >> @Getify where he talks about 'im/mature' optimisation and his thoughts on
> >> this discussion.
>
> >> Personally, I think that it's such a minor tweak that I will always cache
> >> the array length. Why wouldn't you? It doesn't make the code un-readable,
> >> it's obvious to any level developer what's happening (i.e. it's not some of
> >> the more cryptic 'micro-optimisations' that you can see sometimes), and it
> >> does have a testable impact on performance if you don't do it. So (to me) it
> >> seems like an easy choice to just go with caching the length.
>
> >> Kind regards,
> >> Mark
>
> > Thanks Mark, all good points, and a good read. However, in that blog, he
> > does specifically say:
>
> >  Also, notice: I am *not* focusing on esoteric and minute
> > micro-performance details (as some do, and many assumed I was). I made no
> > mention of things like array.push() vs. array[array.length], or str +=
> > "..." vs. str = arr.join(), or ++i vs. i++, or for (i=0; i < arr.length;
> > i++) {...}vs. for (i=0, len=arr.length; i<len; i++) {...}, etc etc etc.
>
> > My feeling is that it does reduce the readability slightly, and I'm not
> > sure whether that's worth it when i *know* it's not going to affect
> > performance.
>
> > Then again, if I got used to using it consistently, the readability issue
> > wouldn't be so big a deal.
>
> > --
> > Nick Morgan
> >http://skilldrick.co.uk
> > @skilldrick <http://twitter.com/skilldrick>
>
> >  --
> > To view archived discussions from the original JSMentors Mailman list:
> > http://www.mail-archive.com/jsment...@jsmentors.com/
Re: Caching array length property Angus Croll 2/19/11 3:35 PM
>>Note I also use ++i over i++ because it's slightly faster on some modern browsers.

I read the same thing on Andrea Giammarchi's site but I don't think its true. Check the ECMA 5 standard. Since a for loop does not use the return value of i++ or ++i the only interesting part is steps 4 and 5 for each case - and they are identical.    

11.3.1   Postfix Increment Operator

The production PostfixExpression : LeftHandSideExpression [no LineTerminator here] ++ is evaluated as follows:
  1. Let lhs be the result of evaluating LeftHandSideExpression.
  2. Throw a SyntaxError exception if the following conditions are all true:
    • Type(lhs) is Reference is true
    • IsStrictReference(lhs) is true
    • Type(GetBase(lhs)) is Enviroment Record
    • GetReferencedName(lhs) is either "eval" or "arguments"
  3. Let oldValue be ToNumber(GetValue(lhs)).
  4. Let newValue be the result of adding the value 1 to oldValue, using the same rules as for the + operator (see 11.6.3).
  5. Call PutValue(lhs, newValue).
  6. Return oldValue.

11.4.4   Prefix Increment Operator ( ++ )

The production UnaryExpression : ++ UnaryExpression is evaluated as follows:
  1. Let expr be the result of evaluating UnaryExpression.
  2. Throw a SyntaxError exception if the following conditions are all true:
    • Type(expr) is Reference is true
    • IsStrictReference(expr) is true
    • Type(GetBase(expr)) is Enviroment Record
    • GetReferencedName(expr) is either "eval" or "arguments"
  3. Let oldValue be ToNumber(GetValue(expr)).
  4. Let newValue be the result of adding the value 1 to oldValue, using the same rules as for the + operator (see 11.6.3).
  5. Call PutValue(expr, newValue).
  6. Return .



Re: [JSMentors] Re: Caching array length property Rob Griffiths 2/19/11 4:01 PM
Whilst I don't disagree the spec suggest that both should be the same, my test on jsperf gave me an insight http://jsperf.com/incremental-loops/6

Obviously, all benchmarks are subject to conditions and I may  have misunderstood the results. But to be fair the numbers are negligible.

While loops on the other hand are blindingly fast.
--
To view archived discussions from the original JSMentors Mailman list: http://www.mail-archive.com/jsmentors@jsmentors.com/

 
To search via a non-Google archive, visit here: http://www.mail-archive.com/jsmentors@googlegroups.com/
 
To unsubscribe from this group, send email to
jsmentors+...@googlegroups.com
Re: [JSMentors] Re: Caching array length property Stefan Weiss 2/19/11 5:13 PM
On 18/02/11 17:35, bytespider wrote:
> for (var i = 0, length = arr.length; i < length; ++i) {
...

> Note I also use ++i over i++ because
> it's slightly faster on some modern browsers but mostly out of habit.

Okay, now we're firmly in micro-optimization land, but I'm curious...
partially because this topic comes up once in a while, and partly
because I also tend to use ++i rather than i++ (purely out of habit).

This used to be a sensible optimization in C once, a long time ago, but
modern compilers like gcc or javac will automatically optimize an
expression like this when its return value is not used (I've appended a
few examples in case you want to confirm it for yourself). As far as I
know, there is no longer any point in preferring pre-increment over
post-increment in a for-loop like this. Same thing goes for C++, as long
as i is a simple type.

Now you say that modern browsers will perform _better_ when you use the
pre-incement. Did you actually test this? I tried to verify it with a
couple of modern engines, but didn't see any difference. I didn't expect
to see any - modern JS engines should have more advanced optimizers than
older ones; they should be better able to recognize that the return
value won't be used and the expression i++ can be optimized. It seems
like most modern engines do this.

From a semantic viewpoint, some people say that ++i expresses the intent
more accurately. From a logical viewpoint, using ++i should never be
slower than i++, regardless of optimizers. From a pragmatic viewpoint -
who cares, they're both fast enough. As I said, I'm just curious.

Before I get flamed: this is a purely academic question. I'm certainly
not suggesting it has any impact on real life JS performance from our
perspective.


stefan

_____

$ cat pre.c
#include <stdio.h>
int main ()
{
    int i;
    for (i = 0; i < 5; ++i) {
        printf("Line %d\n", i);
    }
    return 0;
}

$ cat post.c
#include <stdio.h>
int main ()
{
    int i;
    for (i = 0; i < 5; i++) {
        printf("Line %d\n", i);
    }
    return 0;
}

$ cat pre.java
class Test
{
    static public void main (String args[])
    {
        int i;
        for (i = 0; i < 5; ++i) {
            System.out.printf("Line %d\n", i);
        }
    }
}

$ cat post.java
class Test
{
    static public void main (String args[])
    {
        int i;
        for (i = 0; i < 5; i++) {
            System.out.printf("Line %d\n", i);
        }
    }
}

$ gcc < pre.c -xc -S -o pre.s -
$ md5sum pre.s
d9b04afd3a0c5e95d3492459f736e7ec  pre.s

$ gcc < post.c -xc -S -o post.s -
$ md5sum post.s
d9b04afd3a0c5e95d3492459f736e7ec  post.s

$ cp pre.java Test.java
$ javac Test.java
$ md5sum Test.class
c787c1063aa3d4164d9f2b63b7df8fd2  Test.class

$ cp -f post.java Test.java
$ javac Test.java
$ md5sum Test.class
c787c1063aa3d4164d9f2b63b7df8fd2  Test.class


--
LOAD"Ph'nglui mglw'nafh Cthulhu R'lyeh wgah'nagl fhtagn!",8,1
RUN!

Re: Caching array length property Michael Haufe (TNO) 2/19/11 5:49 PM
This hasn't mattered since IE6 as far as I can tell. There use to be
numerous detailed numbers and reviews on this:

http://homepage.mac.com/rue/JS_Optimization_Techniques/
http://home.earthlink.net/~kendrasg/info/js_opt/jsOptMain.html