About Me

My photo
PLANO, Texas, United States

Saturday, October 3, 2020

Apex CPU Time Limit

The CPU is responsible for executing a program. The CPU is considered a brain and if your brain thinks too much on particular things, you might not be able to utilize your mind effectively in other things. Same in the coding world, If a particular piece of code is eating up the CPU, it will impact the application performance and your application will be slow. Fortunately, Salesforce puts limits in place to prevent one customer from hogging all the server resources.

Due to the multi-tenant nature of the Salesforce platform, different governor limits are introduced to ensure that no customer can monopolize the shared resources. Salesforce platform imposes a CPU usage governor limit to any given execution context, which is approximately 10,000 milliseconds (10 seconds). It means that Apex Code, declarative tools, or a combination in a transaction, must not exceed a ~10-second limit. If transactions consume too much CPU time, they will be shut down as a long-running transaction. For asynchronous Apex this limit is  60,000 milliseconds (60 seconds)

Example-

Let's see I have run the below code in the Anonymous block. When I execute this, I will get the CPU limit error.


string tempvar = 'Manoj Pandey';

for(integer i=0;i<=10000;i++){

   for(integer J=0;J<=100;J++){

   system.debug('Account list :'+i+tempvar);

}


System.LimitException: Apex CPU time limit exceeded

10:04:58.402 (36054302855)|FATAL_ERROR|System.LimitException: Apex CPU time limit exceeded

 



What are the facts behind Apex CPU Limit? 

There are few facts you must know why dealing with the Apex CPU limit:

  • Ap CPU limit exceeded doesn't mean it is caused only due to apex class. The error also involves declarative tools. It is calculated for the executing Apex code and any processes that are called from this code, such as package code, workflows, process builders, and flows. 

  • It is shared with certified managed packages. The certified managed package is a package that has passed the security review for AppExchange. It has its own set of limits for most per-transaction limits. However, Apex CPU Time Limit is an exception.

  • It is non-negotiable. This means we cannot increase the 10-second threshold by tweaking settings, buying more allocations from Salesforce, or work around it by other means. It is an absolute hard limit.

  • It shuts down the execution immediately. 

  • It rolls back all database transactions. For example, you might have done multiple DMLs successfully in the transaction. These DMLs are reverted when this limit hits.

  • Database operations, e.g. the portion of execution time spent in the database for DML, SOQL, and SOSL isn’t counted, nor is waiting time for Apex callouts., SOQL

Is my latest code change responsible for the CPU limit?

Suppose you have deployed a new trigger and you are seeing CPU limit error. It is not unnecessary that your latest code causes this issue.

A key concept to understand is that this limit is shared by all Apex code executing. This includes the customer's code, Process Builder Flows, and all other managed packages installed. You can think of this CPU limit as a bucket of resources. Every time something runs that require CPU time, it will reach into the bucket and take a little bit of CPU time. This is fine until some part of the process reaches into the bucket and there is nothing left. This is when the code gets in trouble and displays an error like "Apex CPU time limit exceeded." There may have been another process using 9.9 seconds of that CPU time, but the next process that runs for only 0.1 seconds is the code that meets trouble for hitting the limit. This is why it sometimes says Apex Trigger C caused the error when in reality it was simply the piece of code to hit the limit, not the piece of code to use up all the resources.


How to Identify the Apex CPU Time Limit culprit?

Sometimes fixing issues is easy but finding the root cause might be difficult. 

  • In some scenarios, it’s easy to spot it. For instance, you see this error popping up on a VisualForce page or you expected a calculated field value that didn’t arrive. Here you have the clue that a CPU Time Limit exception has occurred. 

  • In other scenarios when the code execution runs merely in the background,  it’s much more difficult to catch that it has happened. In my previous example, Trigger C throwing error but the actual culprit was other components. 

Developer Console could help you to find out which consumes most of the CPU time. 

  • Let’s assume that we have enabled the Debug Log and found the Apex CPU Time Limit exception in the Apex trigger C, double click on Log.
  • The second step is to find out what consumes most of the CPU time. However, like the screenshot below, the debug log contains an excessive amount of information. We would like to only know what actions consume how much CPU time. Let’s switch to Analysis Perspective in the Developer Console.
  • Choose Timeline -> Scale 

How can Apex CPU Time Limit Exceeded be avoided?

Apex CPU Time limit exceeded can be avoided using the best practices of Apex. Some of the below points can help to avoid CPU limits

  1. Explore if your business allows you to do the operation asynchronously - In some cases, business processes may not be real-time. If there is a chance to make code execute in @future, this will break the context, and also the CPU time out limit for the asynchronous process is 60seconds(6X of the synchronous process). Consider this if you're at risk of hitting the limit.

  2. Only take necessary data and run a loop- It is essential to filter only specific data while doing a for on a list of records. Too much looping will increase CPU time. The same was true when we had a number of script statements.

  3. Aggregate SOQL usage-Since the database time is not calculated in CPU time it is always better to explore the usage of aggregate SOQL for your business use case. Say you want a summation of the field value of some records. If you use normally for a loop to get these, it is obvious you have spent CPU time there. Instead, try to push your calculation using SUM, AVG aggregate functions at the database layer itself. By doing this you have reduced CPU time and have pushed the process on the database layer itself. Explore options to group by or create some sort of filtering at the database layer. Push your calculations at the database layer to reduce the chances of hitting CPU time out issues.
  4. Avoid Nested loops-We need to be checking on our code when we are using nested loops. Sometimes we can’t avoid them, but sometimes we can use Map.

  5. Avoid Recursion-Having an update call the same update trigger more than once within one transaction can cause problems.

  6. Minimize system debug logs. If any debug is needed, it's good to have a custom setting like

if(isDebugON){
system.debug('This is my custom setting');
}

No comments:

Post a Comment