0

I have the following loop. The length is around 1500 points. But this snippit might get called multiple times on a page load (6-7).

buffer[xname] = [xname];
buffer[yname] = [yname];
for (var i = 0; i < rawdata.length; i++) {
    buffer[xname].push( rawdata[i][0] );
    buffer[yname].push( rawdata[i][1] );
}

I need to do this operation in the browser (it is used to condition the data before plotting them).

Currently this makes the browser very slow.

I tried to use a setTimeout() to ease the event loop a bit. That works but it takes seconds.

Is there any way to make this loop faster? Maybe some sort of mapping?

opcode
  • 419
  • 5
  • 11
  • 4
    Are you sure that's what's causing it to slow down? 1500 loops is nothing, especially if you're only pushing two elements to two different arrays in each iteration. – royhowie Jun 02 '15 at 22:26
  • The issue is that on an analytics page this snippit might get called 6-7 times. Do you think thats still low? – opcode Jun 02 '15 at 22:27
  • 1
    still, 10k loops is nothing. Either the problem lies elsewhere or your page is just taking a while to load because of other asynchronous operations. – royhowie Jun 02 '15 at 22:30

2 Answers2

1

You can reduce the loop to half by doing:

buffer[xname] = [xname];
buffer[yname] = [yname];

var dataLength = rawdata.length;

for (var i = 0; i < dataLength / 2; i++) {
    buffer[xname][i] = rawdata[i][0];
    buffer[yname][i] = rawdata[i][1];

    buffer[xname][dataLength - i -1] = rawdata[dataLength - i -1][0];
    buffer[yname][dataLength - i -1] = rawdata[dataLength - i -1][1];
}

Not sure if the change between using push or direct assignment would impact enough to make the execution time the same.

Carorus
  • 535
  • 2
  • 16
  • This seems unlikely to speed things up; it may well be slower than the original. While it does cut the number of loop iterations by half, this is at the expense of doing more than twice as much work each time through the loop and introducing extra complexity. – Michael Geary Jun 02 '15 at 23:21
  • It's also harder to reason about: what happens if `rawdata` has an odd number of elements? At first I thought it would miss one element in the middle - that's what would happen if this were C code using integers. But JavaScript uses floating point numbers, so it will actually copy that middle element twice in the final loop iteration. (Consider length 3: `dataLength / 2` will be 1.5, so the loop executes with `i = 0` and `i = 1`.) No harm done there, but it is definitely confusing. – Michael Geary Jun 02 '15 at 23:26
  • 1
    Tested this with 15000000 elements array and the time was reduced, not by half but around 25%, certainly adds more complexity to the code, but the number and complexity of access operations are the same than using a normal loop,is just reducing the loop counter, I was aware about the issue with an odd number of elements in the data array, also not sure if is really making the code that confusing. :) – Carorus Jun 02 '15 at 23:43
  • 1
    Now that is interesting! Thank you for testing it, and my apology for assuming that it wouldn't improve the speed. There are some other ways you could optimize the code in addition to unrolling the loop. It would be interesting to compare them in various combinations. OTOH in OP's case there are only 1500 elements which is like nothing, so it is probably something else slowing down the page. – Michael Geary Jun 03 '15 at 00:18
0

Thanks to @royhowie

Why is array.push sometimes faster than array[n] = value?

If you have control over the source of rawdata, you might want to consider changing it so it can be used without additional processing.

Community
  • 1
  • 1
user2182349
  • 9,569
  • 3
  • 29
  • 41
  • Don't quote me, but I'm pretty sure `Array.prototype.push` is (unbelievably, I know) faster than direct assignment in v8. Plus, this method doesn't work if the code snippet is run more than once. – royhowie Jun 02 '15 at 22:30