Skip to main content
added 3369 characters in body
Source Link
salesforce-sas
  • 24.5k
  • 5
  • 44
  • 79

Copying the playground example here as they will be deleted:

app.html:

<template>
    <lightning-button label="Load" onclick={load}>
    </lightning-button>
    <lightning-button label="Test Main" onclick={test}>
    </lightning-button>

    <c-performance-child1 myarray={myarray}></c-performance-child1>
</template>

app.js:

import PerformanceInherit from 'c/performanceInherit';

export default class App extends PerformanceInherit { }

performanceInherit.js:

import { LightningElement, track, api } from 'lwc';

export default class PerformanceInherit extends LightningElement {
    compId = 'parent';

    @api myarray = [];

    load() {
        let myarray = [];
        for (let i = 1; i < 111; i++) {
            myarray.push('elem ' + i);
        }
        this.myarray = myarray;
    }

    test() {
        let t1 = new Date().getTime();
        this.myarray.find(item => false);
        let t2 = new Date().getTime();
        console.log('find ______', this.compId + ' => ', (t2 - t1) + ' ms');

        let t3 = new Date().getTime();
        this.myarray.forEach(item => item);
        let t4 = new Date().getTime();
        console.log('forEach ___', this.compId + ' => ', (t4 - t3) + ' ms');

        let t5 = new Date().getTime();
        this.myarray.filter(item => false);
        let t6 = new Date().getTime();
        console.log('filter ____', this.compId + ' => ', (t6 - t5) + ' ms');

        let t7 = new Date().getTime();
        this.myarray.map(item => item);
        let t8 = new Date().getTime();
        console.log('map _______', this.compId + ' => ', (t8 - t7) + ' ms');

        let t9 = new Date().getTime();
        this.myarray.findIndex(item => false);
        let t10 = new Date().getTime();
        console.log('findIndex _', this.compId + ' => ', (t10 - t9) + ' ms');

        console.log('_________________', this.myarray.length);
    }
}

performanceChild1.html

<template>
    <lightning-button label="Test Parent"
                      onclick={test}>
    </lightning-button>

    <c-performance-child2 myarray={myarray}></c-performance-child2>
</template>

performanceChild1.js

import PerformanceInherit from 'c/performanceInherit';

export default class PerformanceChild1 extends PerformanceInherit { }

performanceChild2.html

<template>
    <lightning-button label="Test Child"
                      onclick={test}>
    </lightning-button>

    <c-performance-child3 myarray={myarray}></c-performance-child3>
</template>

performanceChild2.js

import PerformanceInherit from 'c/performanceInherit';

export default class PerformanceChild2 extends PerformanceInherit {
    constructor() {
        super();
        this.compId = 'child';
    }
}

performanceChild3.html

<template>
    <lightning-button label="Test Grand-Child"
                      onclick={test}>
    </lightning-button>
</template>

performanceChild3.js

import PerformanceInherit from 'c/performanceInherit';

export default class PerformanceChild3 extends PerformanceInherit {
    constructor() {
        super();
        this.compId = 'grand-child';
    }
}

Copying the playground example here as they will be deleted:

app.html:

<template>
    <lightning-button label="Load" onclick={load}>
    </lightning-button>
    <lightning-button label="Test Main" onclick={test}>
    </lightning-button>

    <c-performance-child1 myarray={myarray}></c-performance-child1>
</template>

app.js:

import PerformanceInherit from 'c/performanceInherit';

export default class App extends PerformanceInherit { }

performanceInherit.js:

import { LightningElement, track, api } from 'lwc';

export default class PerformanceInherit extends LightningElement {
    compId = 'parent';

    @api myarray = [];

    load() {
        let myarray = [];
        for (let i = 1; i < 111; i++) {
            myarray.push('elem ' + i);
        }
        this.myarray = myarray;
    }

    test() {
        let t1 = new Date().getTime();
        this.myarray.find(item => false);
        let t2 = new Date().getTime();
        console.log('find ______', this.compId + ' => ', (t2 - t1) + ' ms');

        let t3 = new Date().getTime();
        this.myarray.forEach(item => item);
        let t4 = new Date().getTime();
        console.log('forEach ___', this.compId + ' => ', (t4 - t3) + ' ms');

        let t5 = new Date().getTime();
        this.myarray.filter(item => false);
        let t6 = new Date().getTime();
        console.log('filter ____', this.compId + ' => ', (t6 - t5) + ' ms');

        let t7 = new Date().getTime();
        this.myarray.map(item => item);
        let t8 = new Date().getTime();
        console.log('map _______', this.compId + ' => ', (t8 - t7) + ' ms');

        let t9 = new Date().getTime();
        this.myarray.findIndex(item => false);
        let t10 = new Date().getTime();
        console.log('findIndex _', this.compId + ' => ', (t10 - t9) + ' ms');

        console.log('_________________', this.myarray.length);
    }
}

performanceChild1.html

<template>
    <lightning-button label="Test Parent"
                      onclick={test}>
    </lightning-button>

    <c-performance-child2 myarray={myarray}></c-performance-child2>
</template>

performanceChild1.js

import PerformanceInherit from 'c/performanceInherit';

export default class PerformanceChild1 extends PerformanceInherit { }

performanceChild2.html

<template>
    <lightning-button label="Test Child"
                      onclick={test}>
    </lightning-button>

    <c-performance-child3 myarray={myarray}></c-performance-child3>
</template>

performanceChild2.js

import PerformanceInherit from 'c/performanceInherit';

export default class PerformanceChild2 extends PerformanceInherit {
    constructor() {
        super();
        this.compId = 'child';
    }
}

performanceChild3.html

<template>
    <lightning-button label="Test Grand-Child"
                      onclick={test}>
    </lightning-button>
</template>

performanceChild3.js

import PerformanceInherit from 'c/performanceInherit';

export default class PerformanceChild3 extends PerformanceInherit {
    constructor() {
        super();
        this.compId = 'grand-child';
    }
}
Tweeted twitter.com/StackSalesforce/status/1232636613395652608
Source Link
salesforce-sas
  • 24.5k
  • 5
  • 44
  • 79

Array.find and Array.findIndex has worst performance in LWC Lightning Locker

For the component chain like below:

<container>
    <parent>
        <child>
            <grand-child>

Pass an Array from container to all the way down to grand-child. This is how we should communicate down the hierarchy according to LWC best practices. When we use any array function, the performance is excellent when used in parent but is worst and adversely affected when in grand-child and worst of all the functions affected are find and findIndex

Consider the example in this playground - This will work fine in playground as locker service is disabled but when you test in any dev org/sandbox, you will notice the difference

  1. Click on Load to load array
  2. Click on test buttons to check performance in parent, child and grand-child.

Below are the results:

enter image description here

I found the solution by using JSON.parse and JSON.stringify or else if its only single level array objects then by using shallow copy by Spread syntax. However, we are not supposed to implement our own work-around and so considering this as bug in LWC.

Why are all array functions multi-fold affected with each passing level? And why specially find and findIndex are affected much worse? Is this known issue? If so, is there a fix for this in road-map?