+ Start a Discussion
SeanCenoSeanCeno 

CPU Limit Error: Trigger within Batch Job

All,
We have a few national accounts with large trade volumes. Each National Account has a sales summary consisting of YTD, MTD, QTD, PYTD, etc. When we post new trades every morning, through a batch job, our system is starting to hit a CPU Limit Error. I was able to recreate this error in the sandbox by loading 5000 trades into 1 National Account and on 1 Contact record. I feel like my code is written pretty efficiently, but every time a trade is inserted, it recalculates the summary, so national accounts or contact records with large trade volumes is causing our system to blow up when the volume is near 200 trades. Can someone look at my code and see if there's a more efficient way to write it? Or does the trade process need to just load 50 at a time? There are also about 5 workflow rules running if a Contact hits a 1st trade in any fund, or a threshold of $250K, $500K, or $1MM.

Debug Logs
14:12:16:000 FATAL_ERROR Class.Contact_RollupTrades.execute: line 81, column 1
14:12:16:000 FATAL_ERROR Trigger.Contact_RollupTrades: line 4, column 1

14:38:37:000 FATAL_ERROR Class.Account_RollupTrades.execute: line 88, column 1
14:38:37:000 FATAL_ERROR Trigger.Account_RollupTrades: line 4, column 1

14:44:37:000 FATAL_ERROR Class.Account_RollupTrades.execute: line 74, column 1
14:44:37:000 FATAL_ERROR Trigger.Account_RollupTrades: line 4, column 1

14:48:51:000 FATAL_ERROR Class.Account_RollupTrades.execute: line 77, column 1
14:47:29:000 FATAL_ERROR Trigger.Account_RollupTrades: line 4, column 1

14:47:29:000 FATAL_ERROR Class.Account_RollupTrades.execute: line 78, column 1
14:47:29:000 FATAL_ERROR Trigger.Account_RollupTrades: line 4, column 1

14:46:06:000 FATAL_ERROR Class.Account_RollupTrades.execute: line 87, column 1
14:46:06:000 FATAL_ERROR Trigger.Account_RollupTrades: line 4, column 1

14:54:45:000 FATAL_ERROR Class.Account_RollupTrades.execute: line 67, column 1
14:54:45:000 FATAL_ERROR Trigger.Account_RollupTrades: line 4, column 1

15:02:01:000 FATAL_ERROR Class.Contact_RollupTrades.execute: line 83, column 1
15:02:01:000 FATAL_ERROR Trigger.Contact_RollupTrades: line 4, column 1

15:03:00:809 CODE_UNIT_FINISHED Trades_CascadeContacts on Trades trigger event AfterInsert for [a08L0000006xNw4, a08L0000006xNw5, a08L0000006xNw6, a08L0000006xNw7, a08L0000006xNw8, a08L0000006xNw9, a08L0000006xNwA, a08L0000006xNwB, a08L0000006xNwC, a08L0000006xNwD, a08L0000006xNwE, a08L0000006xNwF, a08L0000006xNwG, a08L0000006xNwH, a08L0000006xNwI, a08L0000006xNwJ, a08L0000006xNwK, a08L0000006xNwL, a08L0000006xNwM, a08L0000006xNwN, a08L0000006xNwO, a08L0000006xNwP, a08L0000006xNwQ, a08L0000006xNwR, a08L0000006xNwS, a08L0000006xNwT, a08L0000006xNwU, a08L0000006xNwV, a08L0000006xNwW, a08L0000006xNwX, a08L0000006xNwY, a08L0000006xNwZ, a08L0000006xNwa, a08L0000006xNwb, a08L0000006xNwc, a08L0000006xNwd, a08L0000006xNwe, a08L0000006xNwf, a08L0000006xNwg, a08L0000006xNwh, a08L0000006xNwi, a08L0000006xNwj, a08L0000006xNwk, a08L0000006xNwl, a08L0000006xNwm, a08L0000006xNwn, a08L0000006xNwo, a08L0000006xNwp, a08L0000006xNwq, a08L0000006xNwr, a08L0000006xNws, a08L0000006xNwt, a08L0000006xNwu, a08L0000006xNwv, a08L0000006xNww, a08L0000006xNwx, a08L0000006xNwy, a08L0000006xNwz, a08L0000006xNx0, a08L0000006xNx1, a08L0000006xNx2, a08L0000006xNx3, a08L0000006xNx4, a08L0000006xNx5, a08L0000006xNx6, a08L0000006xNx7, a08L0000006xNx8, a08L0000006xNx9, a08L0000006xNxA, a08L0000006xNxB, a08L0000006xNxC, a08L0000006xNxD, a08L0000006xNxE, a08L0000006xNxF, a08L0000006xNxG, a08L0000006xNxH, a08L0000006xNxI, a08L0000006xNxJ, a08L0000006xNxK, a08L0000006xNxL, a08L0000006xNxM, a08L0000006xNxN, a08L0000006xNxO, a08L0000006xNxP, a08L0000006xNxQ, a08L0000006xNxR, a08L0000006xNxS, a08L0000006xNxT, a08L0000006xNxU, a08L0000006xNxV, a08L0000006xNxW, a08L0000006xNxX, a08L0000006xNxY, a08L0000006xNxZ, a08L0000006xNxa, a08L0000006xNxb, a08L0000006xNxc, a08L0000006xNxd, a08L0000006xNxe]

Account Class
public class Account_RollupTrades {
    public Static Account_Setting__c setting = Account_Setting__c.getInstance();
    public Static boolean inprog = false;
    
    public static void execute (Set<Id> accountIds, List<Account> accountsList) {
        Map<Id, Account> accounts = new Map<Id, Account> (AccountsList);
        system.debug ('execute');
        if(setting.Disable_RollupTrades__c != true) {
            //Map<Id, Account> accounts = new Map<Id, Account>();
            for(Id accountId:accountIds) {
                system.debug(accountid);
                accounts.put(accountId,
                   new Account(
                       Id=accountId,
                       YTD_NIOR_I_Sales__c = 0,         YTD_NIOR_I_Shares__c = 0,         QTD_NIOR_I_Sales__c = 0,         QTD_NIOR_I_Shares__c = 0,
                       MTD_NIOR_I_Sales__c = 0,         MTD_NIOR_I_Shares__c = 0,         PY_NIOR_I_Sales__c = 0,          PY_NIOR_I_Shares__c = 0,
                       Total_NIOR_I_Sales__c = 0,       Total_NIOR_I_Shares__c = 0,       YTD_NS_Income_Sales__c = 0,      YTD_NS_Income_Shares__c = 0,
                       QTD_NS_Income_Sales__c = 0,      QTD_NS_Income_Shares__c = 0,      MTD_NS_Income_Sales__c = 0,      MTD_NS_Income_Shares__c = 0,
                       PY_NS_Income_Sales__c = 0,       PY_NS_Income_Shares__c = 0,       Total_NS_Income_Sales__c = 0,    Total_NS_Income_Shares__c = 0,
                       Total_NS_HI_Sales__c = 0,       Total_NS_HI_Shares__c = 0,       YTD_NS_HI_Sales__c = 0,         YTD_NS_HI_Shares__c = 0,
                       QTD_NS_HI_Sales__c = 0,         QTD_NS_HI_Shares__c = 0,         MTD_NS_HI_Sales__c = 0,         MTD_NS_HI_Shares__c = 0,
                       PY_NS_HI_Sales__c = 0,          PY_NS_HI_Shares__c = 0,          Total_NS_Income_II_Sales__c = 0, Total_NS_Income_II_Shares__c = 0,
                       YTD_NS_Income_II_Sales__c = 0,   YTD_NS_Income_II_Shares__c = 0,   QTD_NS_Income_II_Sales__c = 0,   QTD_NS_Income_II_Shares__c = 0,
                       MTD_NS_Income_II_Sales__c = 0,   MTD_NS_Income_II_Shares__c = 0,   PY_NS_Income_II_Sales__c = 0,    PY_NS_Income_II_Shares__c = 0,
                       Rollup_Trades__c = DateTime.now()
                   )
                            );
            }
            Map<String, SObjectField[]>
                ytd = new map<string, sobjectfield[]> {
                    '3910' => new sobjectfield[] { account.YTD_NIOR_I_Sales__c , account.YTD_NIOR_I_Shares__c},
                    '3911' => new sobjectfield[] { account.YTD_NS_Income_Sales__c , account.YTD_NS_Income_Shares__c },
                    '3912' => new sobjectfield[] { account.YTD_NS_HI_Sales__c , account.YTD_NS_HI_Shares__c },
                    '3915' => new sobjectfield[] { account.YTD_NS_Income_II_Sales__c , account.YTD_NS_Income_II_Shares__c }    
                },
                qtd = new map<string, sobjectfield[]> {
                    '3910' => new sobjectfield[] { account.QTD_NIOR_I_Sales__c , account.QTD_NIOR_I_Shares__c},
                    '3911' => new sobjectfield[] { account.QTD_NS_Income_Sales__c , account.QTD_NS_Income_Shares__c },
                    '3912' => new sobjectfield[] { account.QTD_NS_HI_Sales__c , account.QTD_NS_HI_Shares__c },
                    '3915' => new sobjectfield[] { account.QTD_NS_Income_II_Sales__c , account.QTD_NS_Income_II_Shares__c }
                },
                mtd = new map<string, sobjectfield[]> {
                    '3910' => new sobjectfield[] { account.MTD_NIOR_I_Sales__c , account.MTD_NIOR_I_Shares__c},
                    '3911' => new sobjectfield[] { account.MTD_NS_Income_Sales__c , account.MTD_NS_Income_Shares__c },
                    '3912' => new sobjectfield[] { account.MTD_NS_HI_Sales__c , account.MTD_NS_HI_Shares__c },
                    '3915' => new sobjectfield[] { account.MTD_NS_Income_II_Sales__c , account.MTD_NS_Income_II_Shares__c }
                },
                py = new map<string, sobjectfield[]> {
                    '3910' => new sobjectfield[] { account.PY_NIOR_I_Sales__c , account.PY_NIOR_I_Shares__c},
                    '3911' => new sobjectfield[] { account.PY_NS_Income_Sales__c , account.PY_NS_Income_Shares__c },
                    '3912' => new sobjectfield[] { account.PY_NS_HI_Sales__c , account.PY_NS_HI_Shares__c },
                    '3915' => new sobjectfield[] { account.PY_NS_Income_II_Sales__c , account.PY_NS_Income_II_Shares__c }
                },
                total = new map<string, sobjectfield[]> {
                    '3910' => new sobjectfield[] { account.Total_NIOR_I_Sales__c , account.Total_NIOR_I_Shares__c},
                    '3911' => new sobjectfield[] { account.Total_NS_Income_Sales__c , account.Total_NS_Income_Shares__c },
                    '3912' => new sobjectfield[] { account.Total_NS_HI_Sales__c , account.Total_NS_HI_Shares__c },
                    '3915' => new sobjectfield[] { account.Total_NS_Income_II_Sales__c , account.Total_NS_Income_II_Shares__c }
                };
	
	// We make the select in a "for" so instead of selecting to many records at once hitting the heap size limit the for it will take only 200 records to work with at each iteration.
	for(Trades__c[] tradesList : [select Dollar_Amount_of_the_transaction__c, Fund_Number__c, Number_of_Shares_of_the_transaction__c, Resolved_Firm_Trading_ID__c, Resolved_Firm_Trading_IDs__c, Trade_Date__c from Trades__c where Resolved_Firm_Trading_ID__c in :accountIds and Fund_Number__c in ('3910', '3911', '3912', '3915') and Dollar_Amount_of_the_transaction__c != null and Number_of_Shares_of_the_transaction__c != null and Trade_Date__c != null and Dollar_Amount_of_the_transaction__c >= 0 and Number_of_Shares_of_the_transaction__c >= 0]){
        for(trades__c trade: tradesList) {
            
            if(date.today().year() == trade.trade_date__c.year()) {
                system.debug(ytd);
                accounts.get(trade.Resolved_Firm_Trading_ID__c).put(ytd.get(trade.fund_number__c)[0], ((Decimal)accounts.get(trade.Resolved_Firm_Trading_ID__c).get(ytd.get(trade.fund_number__c)[0]))+trade.Dollar_Amount_of_The_Transaction__c);
                accounts.get(trade.Resolved_Firm_Trading_ID__c).put(ytd.get(trade.fund_number__c)[1], ((Decimal)accounts.get(trade.Resolved_Firm_Trading_ID__c).get(ytd.get(trade.fund_number__c)[1]))+trade.Number_of_Shares_of_the_transaction__c);
                
                system.debug(qtd);
                //( (date.ValueOf(date.today().month()).divide(3, 0) == date.ValueOf(trade.trade_date__c.month()).divide(3, 0)) )
                if((((date.today().month() - 1) / 3) + 1) == (((trade.Trade_Date__c.month() - 1) / 3) + 1))   {
                    accounts.get(trade.Resolved_Firm_Trading_ID__c).put(qtd.get(trade.fund_number__c)[0], ((Decimal)accounts.get(trade.Resolved_Firm_Trading_ID__c).get(qtd.get(trade.fund_number__c)[0]))+trade.Dollar_Amount_of_The_Transaction__c);
                    accounts.get(trade.Resolved_Firm_Trading_ID__c).put(qtd.get(trade.fund_number__c)[1], ((Decimal)accounts.get(trade.Resolved_Firm_Trading_ID__c).get(qtd.get(trade.fund_number__c)[1]))+trade.Number_of_Shares_of_the_transaction__c);
                    
                    system.debug(mtd);
                    if(date.today().month()==trade.trade_date__c.month()) {
                        accounts.get(trade.Resolved_Firm_Trading_ID__c).put(mtd.get(trade.fund_number__c)[0], ((Decimal)accounts.get(trade.Resolved_Firm_Trading_ID__c).get(mtd.get(trade.fund_number__c)[0]))+trade.Dollar_Amount_of_The_Transaction__c);
                        accounts.get(trade.Resolved_Firm_Trading_ID__c).put(mtd.get(trade.fund_number__c)[1], ((Decimal)accounts.get(trade.Resolved_Firm_Trading_ID__c).get(mtd.get(trade.fund_number__c)[1]))+trade.Number_of_Shares_of_the_transaction__c);
                    }
                }
            } else if(date.today().year()-1==trade.trade_date__c.year()) {
                accounts.get(trade.Resolved_Firm_Trading_ID__c).put(py.get(trade.fund_number__c)[0], ((Decimal)accounts.get(trade.Resolved_Firm_Trading_ID__c).get(py.get(trade.fund_number__c)[0]))+trade.Dollar_Amount_of_The_Transaction__c);
                accounts.get(trade.Resolved_Firm_Trading_ID__c).put(py.get(trade.fund_number__c)[1], ((Decimal)accounts.get(trade.Resolved_Firm_Trading_ID__c).get(py.get(trade.fund_number__c)[1]))+trade.Number_of_Shares_of_the_transaction__c);
            }
            
            accounts.get(trade.Resolved_Firm_Trading_ID__c).put(total.get(trade.fund_number__c)[0], ((Decimal)accounts.get(trade.Resolved_Firm_Trading_ID__c).get(total.get(trade.fund_number__c)[0]))+trade.Dollar_Amount_of_The_Transaction__c);
            accounts.get(trade.Resolved_Firm_Trading_ID__c).put(total.get(trade.fund_number__c)[1], ((Decimal)accounts.get(trade.Resolved_Firm_Trading_ID__c).get(total.get(trade.fund_number__c)[1]))+trade.Number_of_Shares_of_the_transaction__c);
        }
            }
        }
        inprog = true;
        update accounts.values();
        inprog = false;
    }
}

Account Trigger
trigger Account_RollupTrades on Account (after update) {
    if(Account_RollupTrades.inprog == false) {
        //set<ID> sID = new set<ID> (trigger.newMap.keySet());
        Account_RollupTrades.execute(trigger.newMap.keySet(), trigger.new);
    }
}

Contact Class
public class Contact_RollupTrades {
    public Static Contact_Setting__c setting = Contact_Setting__c.getInstance();
	public static boolean inprog = false;

    public static void execute(Set<Id> contactIds, List<Contact> contactsList) {
        Map<Id, Contact> contacts = new Map<Id, Contact>(ContactsList);
        system.debug('execute');
        if(setting.Disable_Contact_Rollup__c != true) {
            //Map<Id, Contact> contacts = new Map<Id, Contact>();
            for(Id contactId:contactIds) {
                system.debug(contactid);
                contacts.put(contactId,
                    new Contact(
                        Id=contactId,
                        YTD_NIOR_I_Sales__c = 0,       YTD_NIOR_I_Shares__c = 0,       QTD_NIOR_I_Sales__c = 0,         QTD_NIOR_I_Shares__c = 0,
                        MTD_NIOR_I_Sales__c = 0,       MTD_NIOR_I_Shares__c = 0,       PY_NIOR_I_Sales__c = 0,          PY_NIOR_I_Shares__c = 0,
                        Total_NIOR_I_Sales__c = 0,     Total_NIOR_I_Shares__c = 0,     YTD_NS_Income_Sales__c = 0,      YTD_NS_Income_Shares__c = 0,
                        QTD_NS_Income_Sales__c = 0,    QTD_NS_Income_Shares__c = 0,    MTD_NS_Income_Sales__c = 0,      MTD_NS_Income_Shares__c = 0,
                        PY_NS_Income_Sales__c = 0,     PY_NS_Income_Shares__c = 0,     Total_NS_Income_Sales__c = 0,    Total_NS_Income_Shares__c = 0,
                        Total_NS_HI_Sales__c = 0,     Total_NS_HI_Shares__c = 0,     YTD_NS_HI_Sales__c = 0,         YTD_NS_HI_Shares__c = 0,
                        QTD_NS_HI_Sales__c = 0,       QTD_NS_HI_Shares__c = 0,       MTD_NS_HI_Sales__c = 0,         MTD_NS_HI_Shares__c = 0,
                        PY_NS_HI_Sales__c = 0,        PY_NS_HI_Shares__c = 0,        Total_NS_Income_II_Sales__c = 0, Total_NS_Income_II_Shares__c = 0,
                        YTD_NS_Income_II_Sales__c = 0, YTD_NS_Income_II_Shares__c = 0, QTD_NS_Income_II_Sales__c = 0,   QTD_NS_Income_II_Shares__c = 0,
                        MTD_NS_Income_II_Sales__c = 0, MTD_NS_Income_II_Shares__c = 0, PY_NS_Income_II_Sales__c = 0,    PY_NS_Income_II_Shares__c = 0,
                        YES_NIOR_I_Sales__c = 0,       YES_NIOR_I_Shares__c = 0,       YES_NS_HI_Sales__c = 0,          YES_NS_HI_Shares__c=0,
                        YES_NS_Income_II_Sales__c = 0, YES_NS_Income_II_Shares__c = 0, YES_NS_Income_Sales__c = 0,      YES_NS_Income_Shares__c = 0,
                        Rollup_Trades__c = DateTime.now()
                    )
                            );
            }
            Map<String, SObjectField[]>
                ytd = new map<string, sobjectfield[]> {
                    '3910' => new sobjectfield[] { contact.YTD_NIOR_I_Sales__c , contact.YTD_NIOR_I_Shares__c},
                    '3911' => new sobjectfield[] { contact.YTD_NS_Income_Sales__c , contact.YTD_NS_Income_Shares__c },
                    '3912' => new sobjectfield[] { contact.YTD_NS_HI_Sales__c , contact.YTD_NS_HI_Shares__c },
                    '3915' => new sobjectfield[] { contact.YTD_NS_Income_II_Sales__c , contact.YTD_NS_Income_II_Shares__c }    
                },
                qtd = new map<string, sobjectfield[]> {
                    '3910' => new sobjectfield[] { contact.QTD_NIOR_I_Sales__c , contact.QTD_NIOR_I_Shares__c},
                    '3911' => new sobjectfield[] { contact.QTD_NS_Income_Sales__c , contact.QTD_NS_Income_Shares__c },
                    '3912' => new sobjectfield[] { contact.QTD_NS_HI_Sales__c , contact.QTD_NS_HI_Shares__c },
                    '3915' => new sobjectfield[] { contact.QTD_NS_Income_II_Sales__c , contact.QTD_NS_Income_II_Shares__c }
                },
                mtd = new map<string, sobjectfield[]> {
                    '3910' => new sobjectfield[] { contact.MTD_NIOR_I_Sales__c , contact.MTD_NIOR_I_Shares__c},
                    '3911' => new sobjectfield[] { contact.MTD_NS_Income_Sales__c , contact.MTD_NS_Income_Shares__c },
                    '3912' => new sobjectfield[] { contact.MTD_NS_HI_Sales__c , contact.MTD_NS_HI_Shares__c },
                    '3915' => new sobjectfield[] { contact.MTD_NS_Income_II_Sales__c , contact.MTD_NS_Income_II_Shares__c }
                },
                yes = new map<string, sobjectfield[]> {
                    '3910' => new sobjectfield[] { contact.YES_NIOR_I_Sales__c , contact.YES_NIOR_I_Shares__c},
                    '3911' => new sobjectfield[] { contact.YES_NS_Income_Sales__c , contact.YES_NS_Income_Shares__c },
                    '3912' => new sobjectfield[] { contact.YES_NS_HI_Sales__c , contact.YES_NS_HI_Shares__c },
                    '3915' => new sobjectfield[] { contact.YES_NS_Income_II_Sales__c , contact.YES_NS_Income_II_Shares__c }
                },
                py = new map<string, sobjectfield[]> {
                    '3910' => new sobjectfield[] { contact.PY_NIOR_I_Sales__c , contact.PY_NIOR_I_Shares__c},
                    '3911' => new sobjectfield[] { contact.PY_NS_Income_Sales__c , contact.PY_NS_Income_Shares__c },
                    '3912' => new sobjectfield[] { contact.PY_NS_HI_Sales__c , contact.PY_NS_HI_Shares__c },
                    '3915' => new sobjectfield[] { contact.PY_NS_Income_II_Sales__c , contact.PY_NS_Income_II_Shares__c }
                },
                total = new map<string, sobjectfield[]> {
                    '3910' => new sobjectfield[] { contact.Total_NIOR_I_Sales__c , contact.Total_NIOR_I_Shares__c},
                    '3911' => new sobjectfield[] { contact.Total_NS_Income_Sales__c , contact.Total_NS_Income_Shares__c },
                    '3912' => new sobjectfield[] { contact.Total_NS_HI_Sales__c , contact.Total_NS_HI_Shares__c },
                    '3915' => new sobjectfield[] { contact.Total_NS_Income_II_Sales__c , contact.Total_NS_Income_II_Shares__c }
                };
	// We make the select in a "for" so instead of selecting to many records at once hitting the heap size limit the for it will take only 200 records to work with at each iteration.
	for(Trades__c[] tradesList : [select Dollar_Amount_of_the_transaction__c, Fund_Number__c, Number_of_Shares_of_the_transaction__c, Resolved_to_Rep_Trading_ID__c, Trade_Date__c from Trades__c where Resolved_to_Rep_Trading_ID__c in :contactIds and Fund_Number__c in ('3910', '3911','3912', '3915') and Dollar_Amount_of_the_transaction__c != null and Number_of_Shares_of_the_transaction__c != null and Trade_Date__c != null and Dollar_Amount_of_the_transaction__c >= 0 and Number_of_Shares_of_the_transaction__c >= 0]){
        for(trades__c trade:tradesList) {
            
            system.debug(ytd);
            if(date.today().year() == trade.trade_date__c.year()) {
                contacts.get(trade.Resolved_to_Rep_Trading_Id__c).put(ytd.get(trade.fund_number__c)[0], ((Decimal)contacts.get(trade.Resolved_to_Rep_Trading_Id__c).get(ytd.get(trade.fund_number__c)[0]))+trade.Dollar_Amount_of_The_Transaction__c);
                contacts.get(trade.Resolved_to_Rep_Trading_Id__c).put(ytd.get(trade.fund_number__c)[1], ((Decimal)contacts.get(trade.Resolved_to_Rep_Trading_Id__c).get(ytd.get(trade.fund_number__c)[1]))+trade.Number_of_Shares_of_the_transaction__c);
                
                system.debug(qtd);
                //( (date.ValueOf(date.today().month()).divide(3, 0) == date.ValueOf(trade.trade_date__c.month()).divide(3, 0)) )
                if((((date.today().month() - 1) / 3) + 1) == (((trade.Trade_Date__c.month() - 1) / 3) + 1))   {
                    contacts.get(trade.Resolved_to_Rep_Trading_Id__c).put(qtd.get(trade.fund_number__c)[0], ((Decimal)contacts.get(trade.Resolved_to_Rep_Trading_Id__c).get(qtd.get(trade.fund_number__c)[0]))+trade.Dollar_Amount_of_The_Transaction__c);
                    contacts.get(trade.Resolved_to_Rep_Trading_Id__c).put(qtd.get(trade.fund_number__c)[1], ((Decimal)contacts.get(trade.Resolved_to_Rep_Trading_Id__c).get(qtd.get(trade.fund_number__c)[1]))+trade.Number_of_Shares_of_the_transaction__c);
                    
                    system.debug(mtd);
                    if(date.today().month()==trade.trade_date__c.month()) {
                        contacts.get(trade.Resolved_to_Rep_Trading_Id__c).put(mtd.get(trade.fund_number__c)[0], ((Decimal)contacts.get(trade.Resolved_to_Rep_Trading_Id__c).get(mtd.get(trade.fund_number__c)[0]))+trade.Dollar_Amount_of_The_Transaction__c);
                        contacts.get(trade.Resolved_to_Rep_Trading_Id__c).put(mtd.get(trade.fund_number__c)[1], ((Decimal)contacts.get(trade.Resolved_to_Rep_Trading_Id__c).get(mtd.get(trade.fund_number__c)[1]))+trade.Number_of_Shares_of_the_transaction__c);
                        
                        system.debug(yes);
                        if(date.today().day()-1==trade.trade_date__c.day()) {
                            contacts.get(trade.Resolved_to_Rep_Trading_Id__c).put(yes.get(trade.fund_number__c)[0], ((Decimal)contacts.get(trade.Resolved_to_Rep_Trading_Id__c).get(yes.get(trade.fund_number__c)[0]))+trade.Dollar_Amount_of_The_Transaction__c);
                            contacts.get(trade.Resolved_to_Rep_Trading_Id__c).put(yes.get(trade.fund_number__c)[1], ((Decimal)contacts.get(trade.Resolved_to_Rep_Trading_Id__c).get(yes.get(trade.fund_number__c)[1]))+trade.Number_of_Shares_of_the_transaction__c);
                        }
                    }
                }
            }else if(date.today().year()-1==trade.trade_date__c.year()) {
                contacts.get(trade.Resolved_to_Rep_Trading_Id__c).put(py.get(trade.fund_number__c)[0], ((Decimal)contacts.get(trade.Resolved_to_Rep_Trading_Id__c).get(py.get(trade.fund_number__c)[0]))+trade.Dollar_Amount_of_The_Transaction__c);
                contacts.get(trade.Resolved_to_Rep_Trading_Id__c).put(py.get(trade.fund_number__c)[1], ((Decimal)contacts.get(trade.Resolved_to_Rep_Trading_Id__c).get(py.get(trade.fund_number__c)[1]))+trade.Number_of_Shares_of_the_transaction__c);
            }
            
            contacts.get(trade.Resolved_to_Rep_Trading_Id__c).put(total.get(trade.fund_number__c)[0], ((Decimal)contacts.get(trade.Resolved_to_Rep_Trading_Id__c).get(total.get(trade.fund_number__c)[0]))+trade.Dollar_Amount_of_The_Transaction__c);
            contacts.get(trade.Resolved_to_Rep_Trading_Id__c).put(total.get(trade.fund_number__c)[1], ((Decimal)contacts.get(trade.Resolved_to_Rep_Trading_Id__c).get(total.get(trade.fund_number__c)[1]))+trade.Number_of_Shares_of_the_transaction__c);

        }
            }
        }
        inprog = true;
        update contacts.values();
        inprog = false;
    }
}

Contact Trigger
trigger Contact_RollupTrades on Contact (after update) {
    if(Contact_RollupTrades.inprog == false) {
        //Set<ID> sID = new Set<ID>(trigger.newMap.keySet());
        Contact_RollupTrades.execute (trigger.newMap.keySet(), trigger.new);
    }
}

 
MithunPMithunP

Hi SeanCeno,

Recently salesforce introduced new governer limit called "CPU time on the Salesforce servers", for Synchronous 10,000 milliseconds and Asynchronous 60,000 milliseconds.

If your lists having large data then don't use nested FOR loops (for loop within for loop) because it will easily reach CPU time, instead use MAP's like below.

Using Nested For loop
 
List<Task> tasks = [SELECT Id, WhoId FROM Task];
List<Contact> contacts = [SELECT Id FROM Contact];

for (Task t : tasks){
    for(Contact c : contacts){
        if (t.WhoId == c.Id){
            //some logic here   
        } 
    }
}


Using Map's
List<Task> tasks = [SELECT Id ... FROM Task];
Map<Id, Contact> contacts = new Map<Id, Contact>([SELECT Id ... FROM Contact]);

for (Task t : tasks){
    Contact c = contacts.get(t.WhoId);
    if(c != null) {
        //some logic here   
    }
}


Best Regards,
Mithun.
 
James LoghryJames Loghry
To be honest, it's hard to follow the code you posted, but it appears to be rather ineffecient, especially when you're iterating through 200 records at a time (the max for triggers), and trying to load in several thousand records.  That's really why you're seeing the CPU time limit hit.  Now how do you make it more efficient and avoid the CPU Limit is the next question.

Do your Accounts have a relationship with Trades, where you could use formulas or rollup summary fields to handle the data, rather than calculating it every time?  This would be the easiest approach if you could make it work.

The next best bet would be having a Batch job.  If you're unfamiliar with batch jobs see the following article from Salesforce: http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_batch_interface.htm

You mentioned your code is batched in your question, which threw me off at first, but it's not really batched by Salesforce terminology.  What I would do is have your integration or data load process load in your Accounts and Contacts first, and then after all is said and done, then quick off the batch process to do the calculation.  This will run asynchronously and update your accounts, contacts, and/or trades.  That is, if the formula approach doesn't work, which I would take a serious look at first.

Best of luck.
SeanCenoSeanCeno
Perhaps if I explained a little more. There is a batch job for Trades for both Accounts and Contacts. I posted both because the error was being thrown in both, but I should've only concentrated on one. My apologies. 

Below is the Class, Trigger, and Batch job for loading Trades for Accounts. When the batch job runs, it loads in the trades into the system, but it also fires off the above code to update each account. Is there a way to seperate the 2? 

I have created a batch job for the rollup summary. I just need this Trades batch job to not trigger the rollup summary and I can run them seperately.

Trades_CascadeAccounts Class
public class Trades_CascadeAccounts {
    public Trades__c[] tradesOldList { set; get; }
    public Trades__c[] tradesNewList { set; get; }
    public Map<Id, Trades__c> tradesOldListMap { set; get; }
    
    public Trades_CascadeAccounts(Trades__c[] tradesOldList, Trades__c[] tradesNewList) {
        this.tradesNewList = tradesNewList == null ? new Trades__c[0] : tradesNewList.clone();
        this.tradesOldList = tradesOldList == null ? new Trades__c[0] : tradesOldList.clone();
        this.tradesOldListMap = new Map<Id, Trades__c>(this.tradesOldList);
    }
    
    public void execute() {
        Set<Id> tradesAccountIds = new Set<Id> {};
            for(Trades__c tradesNew : tradesNewList) {
                Trades__c tradesOld = tradesOldListMap.containsKey(tradesNew.Id) ? tradesOldListMap.get(tradesNew.Id) : new Trades__c();
                tradesAccountIds.addAll(new Set<Id> { tradesOld.Resolved_Firm_Trading_ID__c, tradesNew.Resolved_Firm_Trading_ID__c });
            }
        tradesAccountIds.remove(null);
        
        Account[] accountList = new Account[0];
        for(Id accountId : tradesAccountIds) {
            accountList.add(new Account(Id=AccountId,Rollup_Trades__c=null));
        }
        update accountList;
        //System.debug('Total Number of script statements allowed in this apex code context: ' +  Limits.getLimitScriptStatements());  
    }
}

Trigger
trigger Trades_CascadeAccounts on Trades__c (after delete, after insert, after undelete, after update) {
    Trades__c[] tradesOldList = trigger.IsDelete ? null : trigger.old;
    Trades__c[] tradesNewList = trigger.IsDelete ? trigger.old : trigger.new;
    new Trades_CascadeAccounts(tradesOldList, tradesNewList).execute();
}

Batch
global class Trades_CascadeAccountsBatchable implements Database.Batchable<sObject>{
    global Database.QueryLocator start(Database.BatchableContext batchableContext){
        return Database.getQueryLocator('select Id from Account where ParentId = null');
    }
    global void execute(Database.BatchableContext batchableContext, Account[] accountList) {
        for(Account account : accountList)
            account.Rollup_Trades__c = null;
        update accountList;
    }
    global void finish(Database.BatchableContext batchableContext) {
    }
}

Schedulable Class
global class Trades_CascadeAccountsSchedulable implements Schedulable {
    global void execute(SchedulableContext schedulableContext) {
        Database.executeBatch(new Trades_CascadeAccountsBatchable(), 5);
    }
}


Accounts Rollup Batch Code:

Accounts Batchable
global class Account_RollupTradesBatchable implements Database.Batchable<sObject>{
    global Database.QueryLocator start(Database.BatchableContext batchableContext){
        return Database.getQueryLocator('select Id from Account where ParentId = null');
    }
    
    global void execute(Database.BatchableContext batchableContext, Account[] accountList) {
        for(Account account : accountList)
            account.Rollup_Trades__c = null;
        update accountList;
    }
    
    global void finish(Database.BatchableContext batchableContext) {
        
    }
}

Accounts Schedulable
global class Account_RollupTradesSchedulable implements Schedulable {
    global void execute(SchedulableContext schedulableContext) {
        Database.executeBatch(new Account_RollupTradesBatchable(), 10);
    }
}

 
SeanCenoSeanCeno
Does anybody see a way to reduce the for loop? Or a better way to write it?