3

Theoretical question, if for e.g. I have a big object called Order and it has a tons on props: strings, numbers, arrays, nested objects.

I have a function:

function removeShipment(order) {
    order.shipment.forEach(
        // remove shipment action
    );
}

Which mean I access only one prop (shipment), but send a big object.

From perspective of garbage collection and performance is there a difference, between pass Order and pass Order.shipment?

Because object passed by reference, and don't actually copy Order into variable.

ibrahim mahrir
  • 29,774
  • 5
  • 43
  • 68

2 Answers2

0

As ibrahim mahrir stated in a comment-- though I don't know why they didn't post an answer, because OPs are incentivised to pick a "best answer" & the sole, bewildering response was therefore chosen-- there is no practical performance difference between passing order to your removeShipment method, or passing order.shipment

This is because JavaScript functions are "pass-by-value" for primitive types, like number and boolean, and it uses something known as "call-by-sharing" for passing copies of references for Objects (like your order and assumedly your Array of shipments). The entire object is not copied when passed as a parameter, just a copy of a reference to it in memory. Either approach, passing order or order.shipments, is effectively identical.

I did write a couple timing tests for this, but the actual difference is so small that it's exceptionally difficult to write a test that even properly measures it. I'll include my code at the end for completeness' sake, but from my limited testing in Firefox & Chrome, they were practically identical, as expected.

For another question / answer in the same vein as yours (as well as a great video on why "Micro-benchmarking" often doesn't produce correct results) that corroborates what I wrote, see: does size of argument in a javascript function affects its performance?

See this answer regarding the implications of "call-by-sharing" Is JavaScript a pass-by-reference or pass-by-value language?


You didn's specify what, "remove shipment action" actually "means" in practice. You could just do testOrder.shipments = [] if you just wanted to "remove all shipments" from the order object. They'd be garbage collected at some point after this if nothing else can reach them. I'm just going to iterate through each & perform an addition operation as a stub, as I'm afraid otherwise everything would just be optimised out.

// "num" between 0 inclusive & 26 exclusive
function letter(num)
{
    return String.fromCharCode(num + 65)
}

// Ships have a 3-letter name & a random value between 0 & 1
function getShipment() {
    return { "name": "Ship", "val": Math.random() }
}

// "order" has 100 "Shipments" 
// As well as 676 other named object properties with random "result" values
// e.g. order.AE => Object { result: 14.9815045239037 }
function getOrder() {
    var order = {}
    for (var i = 0; i < 26; i++) 
    for (var j = 0; j < 26; j++) {
        order[letter(i) + letter(j)] = { "result": (i+j) * Math.random() } 
    }
    order.shipments = Array.from({length: 100}).map(getShipment)
    return order
}

function removeShipmentOrder(order) {
    order.shipments.forEach(s => s.val++);
}

function removeShipmentList(shipmentList) {
    shipmentList.forEach(s => s.val++);
}

// Timing tests

var testOrder = getOrder();
console.time()
for(var i = 0; i < 1000000; i++)
    removeShipmentOrder(testOrder)
console.timeEnd()

// Break in-between tests; 
// Running them back-to-back, the second test always took longer.
// I assume it's actually due to some kind of compiler optimisation

var testOrder = getOrder();
console.time()
for(var i = 0; i < 1000000; i++)
    removeShipmentList(testOrder.shipments)
console.timeEnd()
Lovethenakedgun
  • 617
  • 5
  • 21
-1

Created a simple test here https://jsperf.com/passing-object-vs-passing-raw-value

Test results:

  • in Chrome passing object is ~7% slower that passing raw value
  • in Firefox passing object is ~15% slower that passing raw value
  • in IE11 passing object is ~10% slower that passing raw value

This is syntetic test for passing only one variable, so in other cases results may differ

Andrii Muzalevskyi
  • 3,127
  • 15
  • 20
  • This test does not exist anymore. I created one, to try : https://jsperf.com/passing-object-vs-passing-raw-value , and I got a negligible ~1% difference. – Diego Dec 15 '19 at 03:09
  • How is it that both of you wrote code as a test & didn't include it in an answer? Isn't that common SO practice to actually include something relevant like that "within the answer" rather than relying on purely linking to an external resource? – Lovethenakedgun Mar 29 '22 at 06:52