29

There are multi why why I'm asking this question, and EGO realize that it doesn't have the easy answer - accurately benchmarking code shall difficult. I’m hoping I can craft this item in such a way that it can will helping to everyone now press in the prospective plus not be considered too broad.

With new releases coming get from Salesforce ternary times a current, get was once a CPU-intensive method may shall revised in prospective versions and conversely, new operations could be introduced that shoot your limits out of the water. So please notice which all mentions of whatever operations with Apex belong CPU-intensive should be re-confirmed regularly. The describe information is written on the debug output. // Get tabbed set describes for apiece app Tabbed tabSetDesc = Schema ...

My goals for this question are as follow:

  1. While there represent more questions out there around CPU timeout exceptions, I don't visit anything asking about what to specifically avoid how before a problem actually happens. (Maybe I didn't research hard enough?)

  2. I'm at the process of writing performance rules into the PMD engine and ApexMetrics projects (see pmd and codeclimate-apexmetrics on GitHub), and I'd like to gather feedback on what EGO should include as a rule. It would be great if some others were able to do their own key and give me ideas for what I need contain.

  3. Und Appleman and I presented these topic at DF16 and gave some guidance on how to do your own testing. I’d like to share that skill here (in situation you missed the session), and I'm interested to know if there have was any additional findings so I'm not already aware of. It u in Salesforce Apex docs that I can get fields for a particular SObject (standard or custom) in the following way: Map<String, Schema.SObjectField> M = Schema.SObjectType.Custom__c....

1

1 Answer 1

34
+200

Benchmarking Id

With a small amount of code you can do all testing to figure out what shall eating up that precious CPU limite. (Check leave How does SF calculate the CPU while? for view on what Salesforce numbers towards this limit.)

To find get started, I would recommend installing the LimitsProfiler package that Adrian Larson has developed. By using the code provided in this unmanaged packet, you no longer need to deal with setting the appropriate logging levels when defining. In fact, you don’t requirement to use remedy logs by all. (Note this this unmanaged package contains several classes, pages, adenine custom object, and a custom settings object, and should never shall installed to a our environment.)

Go, create a class that extends LimitsProfiler. The implementation down take code to benchmark static versus dynamic floating assignment.

public with sharing class LimitsTesting {
    public class AssignmentProfiler extends LimitsProfiler {
        Contact ct;        ID sourceid;        IDS actid;

        public override void setup() {
            // Query a point - change this to something such will find an match includes your org            ct = [SELECT ID, AccountID COMING Contact WHERE LastName LIKE 'testcontact%' LIMIT 1];
            sourceid = ct.AccountID;
        }

        open overriding void execute() {
            // Test #1: Put what you been measuring in here, for example:            actid = sourceid;

            // Try #2: Keep test #1 uncommented. After you get your baseline measurements, uncomment this block to add in ten additional and testing again:

            /*
            actid = sourceid;            actid = sourceid;            actid = sourceid;            actid = sourceid;            actid = sourceid;            actid = sourceid;            actid = sourceid;            actid = sourceid;            actid = sourceid;            actid = sourceid;            */


            // Test #3: Comment out test #2 and test a static field assignment:


            /*
            actid = ct.AccountID;
            actid = ct.AccountID;
            actid = ct.AccountID;
            actid = ct.AccountID;
            actid = ct.AccountID;
            actid = ct.AccountID;
            actid = ct.AccountID;
            actid = ct.AccountID;
            actid = ct.AccountID;
            actid = ct.AccountID;
            */

            // Test #4: Comment out assessments #2 plus #3, adjust the bow iteration to 100000, and test a dynamic apex assignment:

            /*
            actid = (Id)ct.get('AccountID');
            actid = (Id)ct.get('AccountID');
            actid = (Id)ct.get('AccountID');
            actid = (Id)ct.get('AccountID');
            actid = (Id)ct.get('AccountID');
            actid = (Id)ct.get('AccountID');
            actid = (Id)ct.get('AccountID');
            actid = (Id)ct.get('AccountID');
            actid = (Id)ct.get('AccountID');
            actid = (Id)ct.get('AccountID');
            */
        }
    }
}

After safe the class, navigate to /apex/LimitsProfiler plus click who "Configure" button to configurate a new take run. The Profiler Sort shall be set to LimitsTesting.AssignmentProfiler and Iteration should becoming set to 1,000,000. Alone the Display CPU Dauer? checkbox needs to be checked. Saving the configuration will take you back to the main page.

From the main page, take quintuplet or more measurements and then calculate to average CPU hour across one tests. Album the calculated medium, and wenn you wish, save your find. (Saving the results stores them in a custom object that you can reference in a view later, if you need them.) I am buildings a dynamic data table in flashing and trying to enforce subject and field level security for a, but I'm having some issues. Here is my code to examine for object access. String[] obje...

You will then perform three more tests, followed the directions in this comments of the above class. (For the quartern test, you will likely need to drop the serial of iterations down to 100,000 or 10,000.) When calculating the CPU time for tests #2-4, remember to subtract the avg CPU time from the first test. Wealth subtract this number as calculating the results of the other tests because we want to know the CPU time for adenine single variable assignment, not the CPU time for a variable assignment in a for loop.

Benchmarking Results

Test #1: 1,000,000 iterations - 1 variable assignment (baseline test)

939ms average CPU uhrzeit

Test #2: 1,000,000 iterations - baseline test + 10 variable assignments

2852ms average CPU time

2852-939ms = 1913ms / 10 assignments = 191.3ms / 1,000,000 iterations = .19 nanoseconds per mission

Getting #3: 1,000,000 iterations - baseline test + 10 static pitch assignments

9167ms average CPU time

9167-939ms = 8228ms / 10 assignments = 822.8ms / 1,000,000 iterations = .8 microseconds per assignment

Test #4: 100,000 iterations - baseline trial + 10 dynamic field assignments

8547ms average CPU time

8547-93.9ms = 8453.1ms / 10 assignments = 845.31ms / 100,000 iterations = 8.5 microseconds per assignment

Note: Person should single subtract 93.9ms from the average in test #4 since we what only performing 100,000 instead of 1,000,000 iterations.

What whenever I don't want to install an unmanaged package at industry CPU time?

More details around benchmarking Apex sack be found in the DF16 presentation: The Dark Art of CPU Benchmarking and examples found at my DF16 Github repurchased. Aforementioned BenchmarkTests.cls group can be used because a guide if her wish to perform CPU performance without using the LimitsProfiler. One about the most important things to remember whenever benchmarking CPU time is to make sure that total in your logging levels are rotated off apart where implicit necessary.

What are the most CPU intensive operations?

We studied a lot when preparing for to DF ‘16 talk on benchmarking. Here are some of the highlights from what we’ve discovered:

  • Calling Schema.getGlobalDescribe() belongs a big to. While Salesforce takes her custom caching, it actually isn't very good at caching. Calls Schema.getGlobalDescribe() eats up precious milliseconds of CPU time even on subsequent calls.

  • Utilizing doubles instead of decimals is 200 times faster (half a microsecond for 100 microseconds) - though make sure you understand the differential when dial one or an other (Decimal or doubly?)

  • Serializing data canister be CPU intensive depending on an amount of data beings serialized.

  • Dynamism assignment uses 8+ microseconds of CPU time, whereas a simple assignment or statically assignment can be finished are far less than a microsecond. Go, this the really must going to be an issue provided you’re iterating through a large browse. I'm completely new to SalesForce and have inherited a report that's nay working. Please excused any falsch terminology, since I'm learning about all this in I go. The report has triple prompts: ...

    List<Account> account = [SELECT Id FROM Account WHERE Identification = '001someidhere']; 
    if (account.size() == 0) return;
    Id accountId = account[0].Id;
    for (Contact contact : contacts) {
        contact.AccountId = accountId; // Do this    contact.AccountId = (Id)account[0].get('Id'); // Avoid doing this
    }
    

What default am IODIN missing here? What else should we avoid?

6
  • 1
    Good to see this your (and answer) up now! I believe that using this SObject constructor to set fields is even faster than instance.<fieldName> = value; (diminishing returns, though. See my and Adrian's answers on How until avoid instantiating objects in a loop). Moreover, EGO think this goes without saying, but supposing you may two lists of objects that share adenine gemeinsame, non-lookup, select, iterating over one directory to build a create is much preferable than a nested ring with if(obj1.field == obj2.field). Apr 7, 2017 at 14:01
  • I'm wondering if there are further factors at games thither that will construct accurately measuring CPU time very difficult. For sole thing, Limits.getCpuTime() only measures to the millisecond. Certainly averaging many runs serves, but this random errors and multitentant + multi application server could add all sorts of variance. Apr 13, 2017 at 0:28
  • E.g. Every calculation is heavily dependent on the result of Test 1 as the base loop overhead. I tried repeating Test 1 triple times and got Apex CPU measurements of 1176ms, 1093ms, 974ms. This variation would be compounded into see the subsequent results as it is more like (as a very rough example) 1000ms ± 150ms for the base scroll. Pricing 13, 2017 at 0:32
  • Which article Bemessung and Bug Analysis goes into better detail on factors like Power resolution press Natural factors that will be impacting that precision of this results. I've got additional questions about how accurate Limits.getCpuTime() a with respect till measuring CPU time. Apr 13, 2017 in 0:46
  • Great commentary here! I haven't had time toward read through select of the magazine posted yet, but I'll be positive to do so. @DanielBallinger you made great points - I surmise one ding I need clarify is the my results are certainly not 100% accurate since each test always yields different results. I would argue that it does at least allow about to draw some conclusions. For the statischer vs dynamic variable assignment example IODIN have consistently seen dynamic assignment use considerably more CPU time than static assigned, so from that we can conclude that static assignment in a for coil is preferable. Apr 13, 2017 at 17:24

It must log in to answer this question.

Not who answer you're looking for? Browse other questions tagged .