JavaScript Array Speed vs C Array

By Xah Lee. Date:

having a debate with Fabrice Popineau [https://plus.google.com/+FabricePopineau/posts]

One of the point is to find out just fast/slow is JavaScript's array compared to C. Here's the result. Not scientific but just for fun.

Here is the C code.

void main()
{
  int a[10000000];
  for(int i = 0; i < 10; i++) {
    for(int j = 0; j < 10000000; j++) {
      a[j] = j;
    }}}

save it as xx.c

compile it on linux like this:

gcc -O1 -std=c99 -o xx xx.c

run it like this: time ./xx

on average, C result 0.080 secs on my machine.

JavaScript

// Google Chrome 38, linux, 2014-10-19
function foo() {
    var arr = Array(10000000);
    var i, j;
    for(j = 0; j < 10; j++) {
        for(i = 0; i < 10000000; i=i+1) {
            arr[i] = i;
        } } }
console.time('foo');
foo();
console.timeEnd('foo');
JavaScript array speed test 2014-10-19
Google Chrome, JavaScript array speed test 2014-10-19

Run it in Google Chrome. Open the console F12, and paste in and hit Enter.

On my machine, Google Chrome v38, linux, the result is 260ms, sometimes 300ms.

So, if we take JavaScript as 0.270 sec, and C as 0.08 sec, then the speed factor is 3.3.

WARNING: Bad Benchmark

I don't know C. The C and JavaScript code are both from [Fabrice Popineau https://plus.google.com/+FabricePopineau/posts] (Fabrice is a professor. From what i know, he's a dedicated Common Lisp fan, teaches Java (and hates Java), and he doesn't know anything about JavaScript.) (i did minor tweak to the JavaScript code)

According [Nick Alcock https://plus.google.com/115849739354666812574/posts] (who is a C expert):

the C benchmark is utterly useless. With -O1, GCC emits code that does a tight loop subtracting in a register, then returns, with no stores: with -O2, GCC eliminates everything.

And an loop doing nothing but a subtraction is faster yet, which is what that benchmark is actually doing. Small wonder it's faster than JS. (Or a straight return, which is what it does under -O2.)

Does nobody know how to read assembler or write benchmarks any more, grumble grumble kids these days get off my lawn waves +1 blessed walking stick of store elimination

(I was “the sort of man who had been old at seventeen”, to quote the wonderful Jonathan Strange and Mr Norrell wildly out of context.)

JavaScript Array Warts

Note: JavaScript array is full of warts.

here's a excerpt from chapter 7 of . The Definitive Guide (5th Edition) by David Flanagan.

JavaScript arrays are a specialized form of JavaScript object, and array indexes are really little more than property names that happen to be integers. We’ll talk more about the specializations of arrays elsewhere in this chapter. Implementations typically optimize arrays so that access to numerically indexed array elements is generally significantly faster than access to regular object properties.

[see JavaScript Book by David Flanagan, and Man-made Complexity in Computer Language]

See also:

How's JavaScript Array Implemented?

here's a explanation on how JavaScript array is implemented by browser. BOTH of the answers: http://stackoverflow.com/questions/9233814/are-javascript-arrays-actually-implemented-as-arrays

quoting them in full:

In SpiderMonkey, arrays are implemented basically as C arrays of jsvals. These are referred to as “dense arrays”. However, if you start doing un-array-like things to them — like treating them like objects — their implementation is changed to something which very much resembles objects.

Moral of the story: when you want an array, use an array. When you want an object, use an object.

Oh, a jsval is a sort of variadic type which can represent any possible JavaScript value in a 64 bit C type.

In V8 and Carakan (and presumably Chakra), all (non-host) objects (both those that are arrays and those that aren't) with properties whose names are array indexes (as defined in ES5) are stored as either a dense array (a C array containing some value wrapper) or a sparse array (which is implemented as a binary search tree).

The unified object representation shows through in that it affects enumeration order: with an object, SpiderMonkey and SquirrelFish both give all properties in insertion order; and with an array, they in general (there are special cases in SM at least!) array indexes first then all other properties in insertion order. V8, Carakan, and Chakra always give array indexes first then all other properties in insertion order, regardless of object type.

Original Debate Link

it's a flame fest.

improved benchmark

2014-10-19 here's improved benchmark by Nick, with JavaScript translation by me. First draft, i gotta go, come back tomorrow.

#define _POSIX_C_SOURCE 200809L

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <time.h>

#define SIZE 10000000

long long sum_up(int *a, size_t size);

int main(void)
{
  long long teetotal = 0;
  long long sum = 0;
  size_t i, j;
  int *a = malloc(sizeof(int)*SIZE);
  struct timespec start, end;

  for (i = 0; i < 10; i++) {
    if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start) < 0)
      perror("getting start time");
    for (j = 0; j < SIZE; j++)
      a[j] = j;
    if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end) < 0)
      perror("getting end time");
    teetotal += (((((long long)end.tv_sec) * 1000000000) + end.tv_nsec) -
                ((((long long)start.tv_sec) * 1000000000) + start.tv_nsec));
    sum += sum_up(a, SIZE);
  }

  printf ("Avg time: %llins\nUseless result value: %lli\n", teetotal / 10, sum);
  free(a);
  return 0;
}

save above as loopsum.c

#include <stddef.h>

long long sum_up(int *a, size_t size)
{
  long long s = 0;
  size_t i;

  for (i = 0; i < size; i++)
     s += a[i];

  return s;
}

save above as sum.c

compile it on linux like this:

gcc -std=c99 -Wall -O2 -o loopsum loopsum.c sum.c -lrt
~ $ gcc -std=c99 -Wall -O2 -o loopsum loopsum.c sum.c -lrt
~ $ loopsum
loopsum: command not found
~ $ ./loopsum
Avg time: 12535292ns
Useless result value: 499999950000000
~ $

by Nick Alcock http://www.esperi.org.uk/~nix/benchmarks/loopsum/

JavaScript version

function loopsum() {
    var sum = 0, size = 10000000, a = Array(size), s = 0, i,j;
    for (i = 0; i < 10; i++) {
        s = 0;
        for (j = 0; j < size; j++) { a[j] = j;  s += a[j]; }
        sum += s;
    }
    return sum;
}

console.time("loopsum");
console.log( "Useless result value:" + loopsum());
console.timeEnd("loopsum");
Useless result value: 499999950000000
~/web/xahlee_info/comp/xx $ ./loopsum
Avg time: 43472781ns
Useless result value: 499999950000000
~/web/xahlee_info/comp/xx $ ./loopsum

that's 0.043 secs.

the JavaScript version runs in chrome for 0.46 secs.

C is faster by 10 times.