Print this page

Code more efficiently to avoid “Apex CPU time limit exceeded”

Knowledge Article Number 000232681
Description

Salesforce has a timeout limit for transactions based on CPU usage. If transactions consume too much CPU time, we'll shut them down as a long-running transaction.

Resolution

We only count events that require application server CPU use. There are some things that use the app server CPU that we don't count, which are things beyond your control as a programmer. For example, the time spent in the database retrieving records won't count, nor will time spent waiting for a callout to return. You don’t control when your code needs compilation, so we don’t count that.
 

We'll count almost everything else that happens on the app server, including declarative actions. If DML in your code encounters a validation rule with a formula, we'll count the time spent evaluating that formula. CPU time is calculated for all executions on the Salesforce application servers occurring in one Apex transaction—for the executing Apex code, and any processes that are called from this code, such as package code and workflows. CPU time is private for a transaction and is isolated from other transactions. Operations that don’t consume application server CPU time aren’t counted toward CPU time.
 

What's counted

 
  • All Apex code
  • Library functions exposed in Apex
  • Workflow execution
 

What's not counted

 
  • Database operations, e.g. DML, SOQL
  • SOSL
  • HTTP callouts
 

Best practices to reduce CPU timeout


Now let's go over some of the best practices in code to help reduce the CPU timeout.
 

Using Map based query 

 
List<Account> lstacc=[Select Id from Account limit 10000];

Set<Id> setIds=new Set<Id>();

for(Account a:lstacc){ //More CPU time for sure due to looping

setIds.add(a.id);

}



//Using Map query saves CPU time

//Fetching all account in map

Map<id,account> aMap = new Map<id,account>([Select Id,Name from Account limit 50000]);


//Creating list of accounts

List<account> accList = aMap.values() ;


//Creating set of ids

Set<id> accIds = aMap.keySet() ;



Explore if your business allows you to do the operation asynchronously 


In some cases business process may not be real time and hence if there is a chance to make code execute in @future ,this will break the context and also the CPU time out limit for asynchronous process is 60seconds(6X of synchronous process).So, consider this if you're in trouble of hitting the limit.


Aggregate SOQL usage 


Since the database time is not calculated in CPU time its always better to explore the usage of aggregate SOQL for your business use case .

Say you want summation of field value  of some records ,if you use normal for loop to get these obvious you have spent CPU time there .Instead try to push your calculation using SUM,AVG aggregate functions at the database layer itself so that you have reduced CPU time and have pushed the process on database layer itself.Explore options to group by or create some sort of filtering at database layer and push your calculations at database layer to reduce chances of hitting CPU time out issue .


Only take necessary data and run a loop


This is essential now to filter only specific data while doing a for on a list of records as too much looping will increase CPU time .Same held good when we had no of script statements limit .




promote demote