Bob Napkin
Bob Napkin

Reputation: 566

Why a function work faster with full array than with empty

I have two implements of function, that gets the last element of array.

function first(array) {
  var length = array ? array.length : 0;
  return length ? array[length - 1] : undefined;
}

function second(array) {
  return array ? array[array.length - 1] : undefined;
}

And second function work with full array faster than first, but slowly with empty. Why and how I can fix it?

Benchmark with full array: http://jsperf.com/lodash-f-last/

Benchmark with empty array: http://jsperf.com/lodash-f-last/2

Upvotes: 4

Views: 180

Answers (3)

Omri Aharon
Omri Aharon

Reputation: 17064

To me it seems that second function is quicker with full array because you don't have to do the var length = array ? array.length : 0; like in the first function, which saves you an extra trinary condition.

With an empty array however, the second function is slower since you are forced to do an arr[-1] (because empty array still provides true inside if) which is a getter function and in the first function the condition is if (0) which is false and you simply return undefined.

As for your second question - how to fix it - I assume this will do the trick since it will save you the getter function:

function second(array) {
  return array && array.length ? array[array.length - 1] : undefined;
}

Upvotes: 3

Vyacheslav Egorov
Vyacheslav Egorov

Reputation: 10492

If you want your code to be fast you should never ever read out of bounds: V8 deoptimizes the code that does that.

In you second function you do precisely that - you read out of bounds. Instead do the bounds check before reading:

function xlast(array) {
  return (array && array.length > 0) ? array[array.length - 1] 
                                     : undefined;
}

Upvotes: 4

doldt
doldt

Reputation: 4506

In case of an empty array, it might be the cost of the array lookup, because your algorithms behave differently at zero length, note the control variable of the ? operator:

function first(array) {
  var length = array ? array.length : 0;
  return length ? array[length - 1] : undefined;
}

returns undefined for [] from evaluating the right side of the ?: construct, because 0 evaluates to false.

On the other hand,

function second(array) {
  return array ? array[array.length - 1] : undefined;
}

returns undefined for [] from evaluating array[-1], because [] evaluates to true.

In case of the full array, the second algo is trivially simpler.

Upvotes: 2

Related Questions