Benchmarking Apex CPU

Your code can do the same thing while using less CPU

We are facing a platform limit when developing an Apex logic: synchroneous code must run with less than 10 seconds CPU time (excluding Database access or apex callouts).
If you have developed lots of triggers, each one will consume part of this limit. You will reach this limit probably when doing a bulk update of records.
A tool has been developed to identify if we can do the same logic with different apex code consuming less CPU. It is available for free here: https://www.adminbooster.com/tool#listing=apexbenchmark
You need first to connect to your org, click run, then enter the apex code to be benchmarkes. On the left you can write some apex code to prepare the context, it will not impact what you will monitor. In the middle, this is the code you want to monitor. On the right you define how many times you want to sample the resulting durations. To get better results, it is recommended that you do long loops inside your apex code (such as a for() loop on more than 1000 iterations). The code is providing an simple example.

Lists versus Sets

Do you think accessing a value in a list is the same cost as accessing a value in a set? You are wrong, even if the cost to access the values is the same, the time spent is different.
Let's prepare a big list like this
Set<String> myList=new Set<String>();
for(Integer x=0;x<800000;x++)myList.add('toto'+x);

To retrieve the values from the list, we will do
for(String s:myList){String s2=s;}

Doing 100 iterations, it gives an average score of 1146 ms (the bigger, the slower) on the test POD.
If you are sure your list has unique values, the code logic is exactly the same as using a Set. The preparation code would be
Set<String> myList=new Set<String>();
for(Integer x=0;x<800000;x++)myList.add('toto'+x);
The code to retrieve the values would remain unchanged.
Basically as we only switched our data type, the speed should be the same. The results are giving an average value of 1270ms. This is 10% slower!
As a conclusion, prefer using lists instead of sets. No impact on the apex instructions (in this example), and 10% CPU benefits. Your code will be faster and you are consuming less governor limits.

Looping in the lists

As we have seen that it is quicker to use a List data type, can we make the processing even faster? Yes! Let's see how
First, we will use the List preparation code
String[] myList=new List<String>();
for(Integer x=0;x<800000;x++)myList.add('toto'+x);
Then , we will use the following code to access all values, it is the same logic as the loop in the above example
for(Integer i=myList.size()-1;i>=0;i--){String s2=myList[i];}
Can we get 10% performance increase again? No, we get 254% better performance! That's huge!! Resulting duration score is an average of 451. If you were initialy using a set, you would have a total of 281% better performance.
To conclude, have this in mind: better use lists than sets, and loop in lists using number iterators instead of implicitely.

Call for apex performance tips

If you are discovering other apex area where you can improve CPU usage like above (not best practices such as removing invariants outside of loops, etc..), send me the sample code to be used in the tool and I will extend this page with the findings.

 
© 2018 Jean-Luc Antoine, All Rights Reserved