Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Apex code Benchmarking

768 views

Published on

Apex code Benchmarking
CPU time Limit

Published in: Education
  • You might get some help from HelpWriting.net Success and best regards!
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Be the first to like this

Apex code Benchmarking

  1. 1. Salesforce Apex Hours Apex Code Benchmarking #SalesforceApexHours #FarmingtonHillsSFDCDug Speaker Date Venue/Link Purushottam Bhaigade , Amit Chaudhary Saturday, Dec 7, 2019 10:00 AM EST ( 8:30 PM IST ) Online Farmington Hills Salesforce Developer User Group
  2. 2. Who am I ? Amit Chaudhary (Salesforce MVP) • Active on Salesforce Developer Community • Blogging at http://amitsalesforce.blogspot.in/ • Co-Organizer of – FarmingtonHillsSFDCDug • Follow us @Amit_SFDC or @ApexHours #SalesforceApexHours #FarmingtonHillsSFDCDug
  3. 3. Our Speaker #SalesforceApexHours #FarmingtonHillsSFDCDug Purushottam Bhaigade • Technical Evangelist, Eternus Solutions • Content Leader of – Pune Salesforce Developer Group • Co-Organizer of – Pune Salesforce Architect Summit • Speaker (IndiaDreamin 2X, Hyderabad Trailblazin, Apex Hours for Students, Pune Salesforce DUG) • Blogging at https://forcefeed.dev/ @bhaigadepuru /in/purushottambhaigade
  4. 4. #FarmingtonHillsSFDCdug #SalesforceApexHours Agenda • Cost of Code • CPU time Limit • Benchmarking technique for Code • Benchmarking technique for Declarative • Demo
  5. 5. #FarmingtonHillsSFDCdug #SalesforceApexHours Before Winter’14 • Script limit – Total number of line of Apex code executed • Separate limits for each Managed Package (Aloha) • Trigger Context – 200,000 lines • Async (Batch & Future) – 1,000,000 lines • Workflow, Process Builders, Formulas has no limits at all Trigger
  6. 6. #FarmingtonHillsSFDCdug #SalesforceApexHours What Changed after Winter’14 ?
  7. 7. #FarmingtonHillsSFDCdug #SalesforceApexHours Script Limit were changed to calculate CPU Time usage
  8. 8. #FarmingtonHillsSFDCdug #SalesforceApexHours CPU Time Limits Asynchronous Context 60 Seconds Apply to All code, including Package code Apply to declarative :Workflows, Process Builder, Flows, Validation Rules, Formulas etc. Trigger Context 10 Seconds Apply to All code, including Package code Apply to declarative :Workflows, Process Builder, Flows, Validation Rules, Formulas etc. Enough time for everyone
  9. 9. #FarmingtonHillsSFDCdug #SalesforceApexHours Shared CPU Time Package 1 Package 2 Local Code Workflow Automation etc. Trigger 10 Seconds Trigger 10 Seconds
  10. 10. #FarmingtonHillsSFDCdug #SalesforceApexHours Do you like Maths? Lets Calculate CPU time limits per record…
  11. 11. #FarmingtonHillsSFDCdug #SalesforceApexHours Asynchronous Context 60 / 200 = 300 (milliseconds) Batch of 200 Records Trigger Context 10 / 200 = 50 (milliseconds) Batch of 1000 Records Trigger Context 10 / 1000 = 10 (milliseconds) Asynchronous Context 60 / 1000 = 60 (milliseconds)
  12. 12. #FarmingtonHillsSFDCdug #SalesforceApexHours By the way it applies to all code including local code, packaged code and declarative as well
  13. 13. #FarmingtonHillsSFDCdug #SalesforceApexHours Consequences • You have installed more number of packages? Probably you are at greater risk of running into limits. • Your managed packaged was release before winter’14 and have passed script limit rule it doesn’t mean now it will not hit CPU limit.
  14. 14. #FarmingtonHillsSFDCdug #SalesforceApexHours It’s App A or B? Who gets Blame? App A uses 9.5 seconds App B uses 1 second CPU time out is here.. And App B gets blame..!!
  15. 15. #FarmingtonHillsSFDCdug #SalesforceApexHours Why Software Benchmarking is hard? • Time measurement can’t trusted always, because system performance varies based on time of day and momentary load. • Debug log cost CPU time • You don’t have control on background operations like garbage collection • Result might change with each patch release
  16. 16. #FarmingtonHillsSFDCdug #SalesforceApexHours Benchmarking Apex Code
  17. 17. #FarmingtonHillsSFDCdug #SalesforceApexHours Static vs Dynamic Apex public static void StaticVsDynamicDML() { Integer startCPUTime; // Grab a contact Contact ct = [Select Id, AccountId from Contact where LastName Like 'testcontact%' Limit 1]; ID sourceid = ct.AccountID; ID actid; startCPUTime = Limits.getCpuTime(); for(Integer x=0; x< 100000; x++) { // Put what you are measuring in here } System.debug(LoggingLevel.Error, ' ElapsedCPUTime = ' + String.ValueOf(Limits.getCpuTime()- startCPUTime)); }
  18. 18. #FarmingtonHillsSFDCdug #SalesforceApexHours Single Assignment ~ 0.00422 milliseconds for assignment in loop (422 ms/100000) ~ 0.002171 milliseconds for single assignment in loop (2171 ms/100000/10) for(Integer x=0; x< 100000; x++) { actid = sourceid; } for(Integer x=0; x< 100000; x++) { actid = sourceid; actid = sourceid; actid = sourceid; actid = sourceid; actid = sourceid; actid = sourceid; actid = sourceid; actid = sourceid; actid = sourceid; actid = sourceid; }
  19. 19. #FarmingtonHillsSFDCdug #SalesforceApexHours Dynamic field Assignment ~ 0.02756 milliseconds for single assignment in loop (2756 ms/10000/10) for(Integer x=0; x< 10000; x++) { 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'); }
  20. 20. #FarmingtonHillsSFDCdug #SalesforceApexHours Consequences • Assignment from static field reference is 20x time slower than variable assignment • Assignment from dynamic field reference is 30x time slower than static assignment • Use temporary variable instead of referencing a field multiple times!
  21. 21. #FarmingtonHillsSFDCdug #SalesforceApexHours Apex Time Killers
  22. 22. #FarmingtonHillsSFDCdug #SalesforceApexHours Describe information is cached, but not always as much as you’ll need Account.sObjectType.getDescirbe 1 ms first time, 0.015 ms subsequent getGlobalDescribe 343 items: 13 ms first time, 1 ms subsequent getGlobalDescribe 863 items: 22 ms first time, 6 ms subsequent Conclusion : You can rely on Describe caching for most cases, but never put getGlobalDescibe in loop. Do your own caching – use singleton pattern ISV’s use extra care – you don’t know how big the org will be
  23. 23. #FarmingtonHillsSFDCdug #SalesforceApexHours  Doing lots of Calculations ? Then use doubles instead of decimals Doubles are 200 times faster  Array Iteration for (Account acc : array) – 4 microseconds (with assignment) for (Integer count=0; count < array.size(); count++) – 2.5 microseconds Integer arraySize = array.size(); for (Integer count=0; count < arraySize; count++) – 0.75 microseconds
  24. 24. #FarmingtonHillsSFDCdug #SalesforceApexHours Serializing data Conclusion : Serializing data can eat up CPU time, depending on the amount of data being serialized The amount of CPU time it takes to serialize does not necessarily double when the amount of data is doubled – there’s a lot of variation Similar result were found when serializing a list of IDs JSON.serialize() on 1 string: ~73 microseconds JSON.serialize() on list of 50 string: ~1 ms (~20 microseconds per item) JSON.serialize() on list of 100 string: ~1.9 ms (~18- 19 microseconds per item) JSON.serialize() on list of 200 string: ~3.4 ms (~16- 17 microseconds per item) JSON.serialize() on list of 400 string: ~7 ms (~17-18 microseconds per item)
  25. 25. #FarmingtonHillsSFDCdug #SalesforceApexHours Benchmarking Declarative
  26. 26. #FarmingtonHillsSFDCdug #SalesforceApexHours Time spent evaluating formulas for validation rules or workflow are counted towards the limit. Poor logic in formula Poorly-authored apex logic
  27. 27. #FarmingtonHillsSFDCdug #SalesforceApexHours
  28. 28. #FarmingtonHillsSFDCdug #SalesforceApexHours To benchmark declarative you need After Trigger public class LeadTriggerHandler { public static Integer startTime; public static void processLeadTrigger(){ if(startTime == null){ startTime = Limits.getCpuTime(); return; } system.debug(Logginglevel.error, 'Elapsed CPU time :'+String.valueOf(Limits.getCpuTime()- startTime)); system.debug(Logginglevel.error, 'isInsert '+trigger.isInsert+'isUpdate '+trigger.isUpdate+'isBefore'+trigger.isBefore+'isAfter '+trigger.isAfter); } }
  29. 29. #FarmingtonHillsSFDCdug #SalesforceApexHours Declarative Benchmark Illustration Insert 200 records After insert trigger Workflow process field updates After update trigger Mark start CPU time here Mark end CPU time hereTotal workflow time
  30. 30. #FarmingtonHillsSFDCdug #SalesforceApexHours Code vs Declarative Performance Test Case CPU Time Insert 200 leads – No code 1.1 ms per lead Insert 200 leads – Apex code does logic in a before update trigger 2.2 ms per lead (+1.1 ms) Insert 200 leads – Workflow Rule updates fields 2.8 ms per lead (+1.7 ms) Insert 200 leads – Process updates fields 8.2 ms per lead (+7.1 ms)
  31. 31. #FarmingtonHillsSFDCdug #SalesforceApexHours Declarative Time Killers
  32. 32. #FarmingtonHillsSFDCdug #SalesforceApexHours Consequences • The cost of sending email notifications via Workflows can add up 15 ms/email (10 field merge template). Ultimately that is 3 seconds for 200 records ! • What is Alternative then? Create task for user – only 0.5 ms per record (tested with basic formula workflow) • Validation Rules Each validation formula function takes about 30 microseconds. Example : 10 validation rules, each with 10 functions, applied to 200 records = 600 ms
  33. 33. #FarmingtonHillsSFDCdug #SalesforceApexHours Death By Interaction
  34. 34. #FarmingtonHillsSFDCdug #SalesforceApexHours In Trigger Context.. App A 2 seconds App B 2 seconds App C 2 seconds 6 Seconds
  35. 35. #FarmingtonHillsSFDCdug #SalesforceApexHours In Trigger Context.. App A 2 seconds App B 2 seconds App C 2 seconds Workflow field update 2 seconds App A 2 seconds App B 2 seconds CPU timeout here.. Random App gets the blame(depending on trigger order) You are innocent doesn’t mean they aren’t going to frame you
  36. 36. #FarmingtonHillsSFDCdug #SalesforceApexHours Lets try out This  Have after insert trigger on Lead – (mention in earlier slide)  Add invocable method with below logic and call it from process builder @InvocableMethod public static void delay(List<Id> leadIds){ List<Integer> largeArray = new List<Integer>(); for(Integer x=0;x<10000;x++){ largeArray.add(x); } for(Id leadId :leadIds){ String jsonStr = JSON.serialize(largeArray); } }
  37. 37. #FarmingtonHillsSFDCdug #SalesforceApexHours
  38. 38. #FarmingtonHillsSFDCdug #SalesforceApexHours Process Silently Fail – Trigger Cause Exception & Rollback Insert 400 Leads After insert trigger (first 200) Process Call Apex Process Updates Leads After insert trigger (last 200) Serialize large arrays CPU timeout happens here.. Aborts this action silently CPU timeout detected here.. Apex error blames the trigger
  39. 39. #FarmingtonHillsSFDCdug #SalesforceApexHours How to prevent this? • Use Limits.getCPUTime() to find out you are getting into trouble, then either exit or go async if you are getting close • Learn more advance architectures to detect reentrancy • Try to use Platform event in your solution for Async operation • Accept that you still may get the blame 
  40. 40. #FarmingtonHillsSFDCdug #SalesforceApexHours Some Good news !! • Figuring out how to optimize applications is fun seriously • Figuring out what went wrong is also fun (unless you’re getting blame ) • You have great job security (unless, of course you’re getting blame )
  41. 41. #FarmingtonHillsSFDCdug #SalesforceApexHours
  42. 42. #FarmingtonHillsSFDCdug #SalesforceApexHours Purushottam Bhaigade purushottambhaigade@gmail.com @bhaigadepuru Credits : Dan Appleman (@danappleman) Robert Watson (@watsonrobertb)
  43. 43. #FarmingtonHillsSFDCdug #SalesforceApexHours Follow us #SalesforceApexHours @ApexHours https://trailblazercommunitygroups.com/farmington-mi- developers-group/ https://www.youtube.com/channel/UChTdRj6YfwqhR_WEF epkcJw/videos https://www.facebook.com/FarmingtonHillsSfdcdug/?ref=b ookmarks

×