javascriptperformancefunctionobjectgarbage-collection

Performance of passing object as argument in javascript


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.


Solution

  • Y 2025

    Measured this again, in 2025, with a simple test - I don't see a notable difference in Chrome and Firefox. All results lie inside interval -3% - +3%.

    I'm surprised by the results with object performance when optimisation is not suppressed. Although code does the same - compiler manages to optimise that version of code somehow in Chrome#135.

    If I try to replicate JS Perf functionality here:

        // secret variable to skip optimisation
        let secret = Math.floor(Math.random() * 100) + 1;
        let secretObj = { v: secret };
        
        // RAW
        let sumA = 0;
        function addToSum(v) {
            sumA += v;
        }
        function testRaw() {
            sumA = 0;
            for (let i = 0; i < 10000000; i++) {
                addToSum(secret);
            }
        }
    
        // OBJECT
        let sumB = 0;
        function addToSumB(v) {
            sumB += v.v;
        }
        function testObj() {
            sumB = 0;
            for (let i = 0; i < 10000000; i++) {
                addToSumB(secretObj);
            }
        }
    
        // HELLO OPTIMISER
        function testObjWithOptimizer() {
            sumB = 0;
            // WHEN THIS LINE IS ADDED
            // CHROME WORKS TWO TIMES FASTER
            let notSoSecretObj = { v: secret };
            for (let i = 0; i < 10000000; i++) {
                addToSumB(notSoSecretObj);
            }
        }
    
        function testIt(description, fn) {
            // warmup
            const warmUpShouldEndAt = performance.now() + 100 /* ms */;
            while (performance.now() < warmUpShouldEndAt) {
                fn();
            }
    
            let totalTimeSpent = 0, iterations = 0;
            while (totalTimeSpent < 200 /* ms */) {
                const startAt = performance.now();
                fn();
                const endAt = performance.now();
                const timeSpent = endAt - startAt;
                totalTimeSpent += timeSpent;
                iterations++;
            }
            console.log(description + ": " + (totalTimeSpent / iterations) + "ms");
        }
    
        testIt("Raw", testRaw);
        testIt("Object", testObj);
        testIt("Object when optimisation works", testObjWithOptimizer);


    Y 2017:

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

    Test results:

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