80

How does SalesForce calculate the CPU Time that was introduced in Winter '14? I am seeing varying results from it. Why does the CPU count vary?

I am running a single block of code over and over again in an org with all triggers disabled. There's only a small amount of code executing ( < 100 lines). Im finding that the Limits are all consistently producing the same results except for the CPU time which is varying by as much as 200 milliseconds.

CPU Time for each run of the code:

  • Maximum CPU time: 598 out of 10000
  • Maximum CPU time: 599 out of 10000
  • Maximum CPU time: 618 out of 10000
  • Maximum CPU time: 602 out of 10000
  • Maximum CPU time: 620 out of 10000
  • Maximum CPU time: 595 out of 10000
  • Maximum CPU time: 791 out of 10000 <- Highest CPU time
  • Maximum CPU time: 590 out of 10000 <- Lowest CPU time
  • Maximum CPU time: 581 out of 10000
  • Maximum CPU time: 697 out of 10000
  • Maximum CPU time: 597 out of 10000
  • Maximum CPU time: 687 out of 10000
  • Maximum CPU time: 658 out of 10000
  • Maximum CPU time: 595 out of 10000
  • Maximum CPU time: 620 out of 10000
  • Maximum CPU time: 593 out of 10000
  • Maximum CPU time: 612 out of 10000

The rest of the limits that never change:

  • Number of SOQL queries: 2 out of 100
  • Number of query rows: 572 out of 50000
  • Number of SOSL queries: 0 out of 20
  • Number of DML statements: 2 out of 1150
  • Number of DML rows: 572 out of 10000
  • Number of script statements: 680 out of 200000
  • Maximum heap size: 5433 out of 6000000
  • Number of callouts: 0 out of 10
  • Number of Email Invocations: 0 out of 10
  • Number of fields describes: 0 out of 100
  • Number of record type describes: 0 out of 100
  • Number of child relationships describes: 0 out of 100
  • Number of picklist describes: 0 out of 100
  • Number of future calls: 0 out of 10
66

Josh Kaplan the Apex Product Manager gave quite a detailed blog post on this new governor entitled Script Limits, Begone!. In it he states this...

What does this CPU timeout include? We are only counting things that require application server CPU use. For example, the time spent in the database retrieving records will not count, nor will time spent waiting for a callout to return. There are some things that use the app server CPU that we do not count, which are things beyond your control as a programmer. For example, you don’t control when your code needs compilation, so we don’t count that. We will be counting 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 will count the time spent evaluating that formula.

The limit is non-deterministic which is why your seeing the variance. This could be considered a concern, given the limit it replaced, while troublesome to us, was at least predictable and scoped by namespace. However as you will see from Josh's excellent post (see section 'But I Have Fear And Doubt!') that Salesforce are all over this, monitoring orgs and reviewing any code both past and present that gets close I'm told. Josh has been present on SE a few times, let see if we can grab his attention to see if he would like to comment further beyond the blog statements.

There is also this statement in the documentation under Understanding Execution Governors and Limits. As well as the usual methods on the Limits class.

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. For example, the portion of execution time spent in the database for DML, SOQL, and SOSL isn’t counted, nor is waiting time for Apex callouts.

  • 6
    Note that the 200ms variance represents a traditional problem in multi-tasking systems. The time spent in Apex Code is wall-clock time and not actual CPU time spent. This means that the system task scheduler (the OS) will influence the wall clock time through the process of multitasking. This is outside the influence of any programming language. – sfdcfox Oct 16 '13 at 13:05
  • 2
    Also, I've observed that for simple tasks, it's now possible to get up to 3,000,000 script statements executed before a limit exception, an increase of 15x. – sfdcfox Oct 16 '13 at 13:59
  • 7
    The move from a script statement limit to a CPU limit will provide more flexibility in most cases, but not all. I have this line of code in a trigger if (myNewObject != myOldObject), which was written with the script statement limit in mind so that we didnt have to iterate over every field on the custom object (there's 200) in the trigger to compare the old value with the new value. We are comparing the old and new object instead which uses up 1 script statement but was actually using 10ms approx of CPU time. It blows up with 1000+ records now. – BarCotter Oct 16 '13 at 17:42
  • @BarCotter Is it common to have 1000+ items in a trigger? And why over 200 fields? It sounds like an optimization problem on salesforce's part, though, it shouldn't take 10ms to compare two records like that. It'll be fun to try and figure out how to optimize now. – sfdcfox Oct 23 '13 at 3:09
  • 3
    (2) Also, have you noticed that the Governor Limit of 10,000 ms isn't strictly enforced? My tests suggest you can push the limit by ~50% consistently. – Scott Pelak Oct 23 '13 at 19:35
19

I raised a case with SalesForce to ask them the same question. After a several weeks I finally got a reply to say:

We have consulted our backline team and they have confirmed that time will change as they are subjected to CPU availability.

Processors naturally take a variable amount of time to process code, so it's almost never going to be the exact amount of time with each execution. You will see the same behavior if you do the same thing on your local machine.

The important point here is to know that CPU time will vary when running the same code over and over again. Keep this in mind when writing code that comes close to the CPU limit. I've seen the CPU time vary by as much as 25% from one request to the next. SalesForce could not give me any information on how much of a variation that can be expected.

4

IMO, the dominant source of time variance is garbage collection that happens in the underlying platform, which is written in Java.

Please vote for the idea https://success.salesforce.com/ideaView?id=08730000000kzOTAAY to not account garbage collection time in a request's CPU time.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.