4
\$\begingroup\$

I'm getting more and more into programming js in a functional manner which makes heavy use of multiple returns via tuples (especially useful with recursion). Also, a pattern that I use often is creating simple temporary values for projections

_.chain(arr)
       .filter(...)
       .map(function(x){ return [x.foo, getSomething(x.bar)] })
       .filter(...)
       .reduce(...)

Usually I see tuples in js implemented with arrays [a, b] though of course an object - while annoying to write would be just as valid: {a: a, b: b}.

So for this sort of use-case (creation and light usage of a bunch of temporary objects) I'm curious if there's a significant performance difference so I set up this jsperf.

Object tuple test:

var all = []
for(var x = 0; x < 100; x+=1) 
for(var y = 0; y < 100; y+=1)
  all.push({x: x, y: y})

var mapped = []
for(var i=0; i < all.length; i+=1)
  mapped.push({x: all[i].x, y: all[i].y})

versus array tuple test

var all = []
for(var x = 0; x < 100; x+=1) 
for(var y = 0; y < 100; y+=1)
  all.push([x, y])

var mapped = []
for(var i=0; i < all.length; i+=1)
  mapped.push([all[i][0], all[i][1]])

What do people think? Is this a sufficient test for the concept?

\$\endgroup\$
2
  • \$\begingroup\$ What is it that you want to test, exactly? You are testing several things in that performance test, i.e. creating objects/arrays, pushing objects/arrays to an array, and reading values from an object/array. The test doesn't show how much each part contributes to the execution time. \$\endgroup\$
    – Guffa
    Commented Nov 16, 2014 at 19:32
  • \$\begingroup\$ @Guffa good question, I edited in a common use case that I have in mind \$\endgroup\$ Commented Nov 16, 2014 at 20:10

2 Answers 2

1
\$\begingroup\$

You should consider testing only the creation of the object/array, i.e. [ x, y ] vs. { x: x, y: y }, and also how it reacts to more items:

http://jsperf.com/array-vs-object-tuple

I'd say that the conclusion would be that there is no dramatic performance difference, and they both react reasonably to an increased number of items. Either is cheap enough that the actual performance of the code is usually decided by the actual work of getting the values to put in the object/array.

So, you should normally use the one that makes for conventient use of the result, and maintainable code. Having the ability to name the items in the result can definitely be convenient if you have more than just a few.

\$\endgroup\$
2
  • \$\begingroup\$ Hmm, putting large arrays/objects in the same test isn't really fair. I've never seen the tuple pattern with arrays used for more than three (and really even that is very rare) so you're just skewing results. I also on chrome latest (windows 8) see almost 10x more operations happen for the small object test than the array one. Of course after the first run through v8 will optimize the object so I'm not sure that's relevant either. Finally, Why do you test creation only? After all, creating a tuple is senseless if you don't also access it at least once. \$\endgroup\$ Commented Nov 17, 2014 at 0:56
  • \$\begingroup\$ @GeorgeMauer: The larger arrays and objects is to see how they scale, and that doesn't skew the results at all. Each test is run independently, so testing larger items doesn't affect the test for small items. The result in Chrome shows that they have optimised for small objects, but that they scale very badly. The test is only for creation because that is what you do in the use case that you presented. You can test access of the objects/arrays also, but that should be done in separat tests so that the result can be useful for evaluate anything other thatn the exact test case. \$\endgroup\$
    – Guffa
    Commented Nov 17, 2014 at 9:17
1
\$\begingroup\$

Interesting question,

I would like to add that using objects is easier for debugging since the data will be annotated so to speak. It will also make your code easier to maintain, all[i][0] is meaningless, but all[i].barSomething can be far more meaningful.

From a memory perspective, when I check the heap snapshot in Chrome:
[100,100] has a retained size of 32
{x:100,y:100}has a retained size of 20
{fnordificated: 100, tentententoonstelling: 100} has a retained size of 60

Keep this in mind when creating your tuples, it is not clear what the unit of measure is, I assume bytes.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.