2

I have a Aura Component, inside which I'm doing some calculation inside for loop. In the for loop, I'm iterating around 3100 records, which is taking lot of time to process.

Since the event on which this method is called is onchange, I'm not able to give any other value after giving first value.

What other options I have to process this?

Below is my JS Method:

let priceTable = component.get("v.priceTableList");
let tableLength = priceTable.length -1;
        for(let i=0;i<tableLength; i++){
            if(priceTable[i].Unit__c <= zeroYear.Jan_Grid_kWh__c && priceTable[i].Unit_10__c > zeroYear.Jan_Grid_kWh__c){
                
                zeroYear.Jan_Charges__c = Math.round(priceTable[i].Price__c);
            }
            
            if(priceTable[i].Unit__c <= zeroYear.Feb_Grid_kWh__c && priceTable[i].Unit_10__c > zeroYear.Feb_Grid_kWh__c){
                zeroYear.Feb_Charges__c = Math.round(priceTable[i].Price__c);
            }
            
            if(priceTable[i].Unit__c <= zeroYear.Mar_Grid_kWh__c && priceTable[i].Unit_10__c > zeroYear.Mar_Grid_kWh__c){
                zeroYear.Mar_Charges__c = Math.round(priceTable[i].Price__c);
            }
            
            if(priceTable[i].Unit__c <= zeroYear.Apr_Grid_kWh__c && priceTable[i].Unit_10__c > zeroYear.Apr_Grid_kWh__c){
                zeroYear.Apr_Charges__c = Math.round(priceTable[i].Price__c);
            }
            
            if(priceTable[i].Unit__c <= zeroYear.May_Grid_kWh__c && priceTable[i].Unit_10__c > zeroYear.May_Grid_kWh__c){
                zeroYear.May_Charges__c = Math.round(priceTable[i].Price__c);
            }
            
            if(priceTable[i].Unit__c <= zeroYear.Jun_Grid_kWh__c && priceTable[i].Unit_10__c > zeroYear.Jun_Grid_kWh__c){
                zeroYear.Jun_Charges__c = Math.round(priceTable[i].Price__c);
            }
            
            if(priceTable[i].Unit__c <= zeroYear.Jul_Grid_kWh__c && priceTable[i].Unit_10__c > zeroYear.Jul_Grid_kWh__c){
                zeroYear.Jul_Charges__c = Math.round(priceTable[i].Price__c);
            }
            
            if(priceTable[i].Unit__c <= zeroYear.Aug_Grid_kWh__c && priceTable[i].Unit_10__c > zeroYear.Aug_Grid_kWh__c){
                zeroYear.Aug_Charges__c = Math.round(priceTable[i].Price__c);
            }
            
            if(priceTable[i].Unit__c <= zeroYear.Sep_Grid_kWh__c && priceTable[i].Unit_10__c > zeroYear.Sep_Grid_kWh__c){
                zeroYear.Sep_Charges__c = Math.round(priceTable[i].Price__c);
            }
            
            if(priceTable[i].Unit__c <= zeroYear.Oct_Grid_kWh__c && priceTable[i].Unit_10__c > zeroYear.Oct_Grid_kWh__c){
                zeroYear.Oct_Charges__c = Math.round(priceTable[i].Price__c);
            }
            
            if(priceTable[i].Unit__c <= zeroYear.Nov_Grid_kWh__c && priceTable[i].Unit_10__c > zeroYear.Nov_Grid_kWh__c){
                zeroYear.Nov_Charges__c = Math.round(priceTable[i].Price__c);
            }
            
            if(priceTable[i].Unit__c <= zeroYear.Dec_Grid_kWh__c && priceTable[i].Unit_10__c > zeroYear.Dec_Grid_kWh__c){
                zeroYear.Dec_Charges__c = Math.round(priceTable[i].Price__c);
            }
            
            //
            if(priceTable[i].Unit__c <= accRec.January__c && priceTable[i].Unit_10__c > accRec.January__c){
                zeroYear.January_Belco_w_o_solar__c = Math.round(priceTable[i].Price__c);
            }
            
            if(priceTable[i].Unit__c <= accRec.February__c && priceTable[i].Unit_10__c > accRec.February__c){
                zeroYear.February_Belco_w_o_solar__c = Math.round(priceTable[i].Price__c);
            }
            
            if(priceTable[i].Unit__c <= accRec.March__c && priceTable[i].Unit_10__c > accRec.March__c){
                zeroYear.March_Belco_w_o_solar__c = Math.round(priceTable[i].Price__c);
            }
            
            if(priceTable[i].Unit__c <= accRec.April__c && priceTable[i].Unit_10__c > accRec.April__c){
                zeroYear.April_Belco_w_o_solar__c = Math.round(priceTable[i].Price__c);
            }
            
            if(priceTable[i].Unit__c <= accRec.May__c && priceTable[i].Unit_10__c > accRec.May__c){
                zeroYear.May_Belco_w_o_solar__c = Math.round(priceTable[i].Price__c);
            }
            
            if(priceTable[i].Unit__c <= accRec.June__c && priceTable[i].Unit_10__c > accRec.June__c){
                zeroYear.June_Belco_w_o_solar__c = Math.round(priceTable[i].Price__c);
            }
            
            if(priceTable[i].Unit__c <= accRec.July__c && priceTable[i].Unit_10__c > accRec.July__c){
                zeroYear.July_Belco_w_o_solar__c = Math.round(priceTable[i].Price__c);
            }
            
            if(priceTable[i].Unit__c <= accRec.August__c && priceTable[i].Unit_10__c > accRec.August__c){
                zeroYear.August_Belco_w_o_solar__c = Math.round(priceTable[i].Price__c);
            }
            
            if(priceTable[i].Unit__c <= accRec.September__c && priceTable[i].Unit__c > accRec.September__c){
                zeroYear.September_Belco_w_o_solar__c = Math.round(priceTable[i].Price__c);
            }
            
            if(priceTable[i].Unit__c <= accRec.October__c && priceTable[i].Unit_10__c > accRec.October__c){
                zeroYear.October_Belco_w_o_solar__c = Math.round(priceTable[i].Price__c);
            }
            
            if(priceTable[i].Unit__c <= accRec.November__c && priceTable[i].Unit_10__c > accRec.November__c){
                zeroYear.November_Belco_w_o_solar__c = Math.round(priceTable[i].Price__c);
            }
            
            if(priceTable[i].Unit__c <= accRec.December__c && priceTable[i].Unit_10__c > accRec.December__c){
                console.log('>>> priceTable[i].Price__c... '+priceTable[i].Price__c);
                console.log('>>> priceTable[i].Unit__c... '+priceTable[i].Unit__c);
                
                zeroYear.December_Belco_w_o_solar__c = Math.round(priceTable[i].Price__c);
            }
        }
5
  • It might be better idea to move Your calculation on apex side as You need to handle around 3100 records. BTW You can create some inner loop instead of multiple if conditions. Commented Oct 26, 2021 at 17:27
  • 1
    @gpoluch client side can be much faster, you just need this one simple trick. (I'm writing it up now).
    – sfdcfox
    Commented Oct 26, 2021 at 17:27
  • @sfdcfox I belive that can be much faster with tricks but I wonder what is the business case that require passing around 3100 records to an Aura Component Commented Oct 26, 2021 at 17:37
  • 1
    @gpoluch Apex is slower than JS, the cost of bandwidth is usually worth the price. Also, you have no governor limits in JS, so you can leave Apex to do the part it needs to do (e.g. saving data).
    – sfdcfox
    Commented Oct 26, 2021 at 17:50
  • @sfdcfox You are right. When I saw the code first time I have some lazy loading in my mind. Commented Oct 26, 2021 at 18:00

1 Answer 1

5

As I've stated about LWC a few times, the problem is not technically Aura, but rather the Lightning Locker Service. Lightning Web Security will help alleviate the problem, but for now, the solution is to clone the data before using it. You can also heavily optimize this code.

Here's my implementation of your code:

let priceTable = component.get("v.priceTableList");
let fields = [
    { monthChargeField: 'Jan_Charges__c', kWhField: 'Jan_Grid_kWh__c', monthField: 'January__c'  , solarField: 'January_Belco_w_o_solar__c'  },
    { monthChargeField: 'Feb_Charges__c', kWhField: 'Feb_Grid_kWh__c', monthField: 'February__c' , solarField: 'February_Belco_w_o_solar__c' },
    { monthChargeField: 'Mar_Charges__c', kWhField: 'Mar_Grid_kWh__c', monthField: 'March__c'    , solarField: 'March_Belco_w_o_solar__c'    },
    { monthChargeField: 'Apr_Charges__c', kWhField: 'Apr_Grid_kWh__c', monthField: 'April__c'    , solarField: 'April_Belco_w_o_solar__c'    },
    { monthChargeField: 'May_Charges__c', kWhField: 'May_Grid_kWh__c', monthField: 'May__c'      , solarField: 'May_Belco_w_o_solar__c'      },
    { monthChargeField: 'Jun_Charges__c', kWhField: 'Jun_Grid_kWh__c', monthField: 'June__c'     , solarField: 'June_Belco_w_o_solar__c'     },
    { monthChargeField: 'Jul_Charges__c', kWhField: 'Jul_Grid_kWh__c', monthField: 'July__c'     , solarField: 'July_Belco_w_o_solar__c'     },
    { monthChargeField: 'Aug_Charges__c', kWhField: 'Aug_Grid_kWh__c', monthField: 'August__c'   , solarField: 'August_Belco_w_o_solar__c'   },
    { monthChargeField: 'Sep_Charges__c', kWhField: 'Sep_Grid_kWh__c', monthField: 'September__c', solarField: 'September_Belco_w_o_solar__c'},
    { monthChargeField: 'Oct_Charges__c', kWhField: 'Oct_Grid_kWh__c', monthField: 'October__c'  , solarField: 'October_Belco_w_o_solar__c'  },
    { monthChargeField: 'Nov_Charges__c', kWhField: 'Nov_Grid_kWh__c', monthField: 'November__c' , solarField: 'November_Belco_w_o_solar__c' },
    { monthChargeField: 'Dec_Charges__c', kWhField: 'Dec_Grid_kWh__c', monthField: 'December__c' , solarField: 'December_Belco_w_o_solar__c' }
]

[...priceTable].slice(0, -1).forEach(row => {
    let price = Math.round(row.Price__c);
    fields.forEach(field => {
        if(row.Unit__c <= zeroYear[field.kWhField] && row.Unit_10__c > zeroYear[field.kWhField]) {
            zeroYear[field.monthChargeField] = price;
        }
        if(row.Unit__c <= accRec[field.monthField] && row.Unit_10__c > accRec[field.monthField]) {
            zeroYear[field.solarField] = price;
        }
    })
})

Here, we use [...array] to shallow copy the array, and then Array.prototype.slice to copy the part of the array you want to work with, rather than repeatedly calling priceTable[i], which I've explained before is very expensive in Lightning Locker Service.

We also take advantage of the dynamic access nature of JavaScript to change the logic from 24 if statements to just 2, and we also use Array.prototype.forEach, which should be your default way of handling for(index = 0; index < size; index++) type loops (also be aware of transformation with Array.prototype.map). In fact, I'd recommend you read Array and get familiar with the various tools that are built-in to the language, like some, every, reduce, etc.

2
  • 1
    @gpoluch Aura does support arrow functions. The main performance sink is Locker Service + individual array accesses, which this code avoids by using slice/forEach. We only pay the "cost" of LS filtering once instead of 6 x 24 x 3100 (about 450k) times, which should provide at about a 450,000x performance boost.
    – sfdcfox
    Commented Oct 26, 2021 at 18:00
  • Yep I agree with You @sfdcfox. Thx for nice approach. Commented Oct 26, 2021 at 18:02

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .