Expensive describe or metadata call inside a loop
ID |
apex.performance.high_cost_in_loop |
Severity |
high |
Remediation Complexity |
medium |
Remediation Risk |
low |
Remediation Effort |
medium |
Resource |
Performance |
Language |
Apex |
Description
Reports a schema describe call, a Limits reading or an email send written inside a for or while loop.
Rationale
Schema.getGlobalDescribe() builds a map of every object in the org - a call measured in hundreds of milliseconds on a large org - and it returns the same map every time. Calling it per iteration multiplies that cost by the batch size and spends the transaction’s ten-second CPU budget on work whose result never changes. Messaging.sendEmail in a loop is the same shape against a much harder limit: ten email invocations per transaction.
The following code illustrates the pattern detected by this rule:
public class DescribeUsage {
public void perRecord(List<Account> accts) {
for (Account a : accts) {
// FLAGGED: Expensive describe or metadata call inside a loop
Map<String, Schema.SObjectType> types = Schema.getGlobalDescribe();
// FLAGGED: Expensive describe or metadata call inside a loop
Messaging.sendEmail(new List<Messaging.SingleEmailMessage>());
System.debug(types.size());
}
}
public void perIterationReceiver(List<Schema.SObjectField> fields) {
for (Schema.SObjectField f : fields) {
Schema.DescribeFieldResult dfr = f.getDescribe();
System.debug(LoggingLevel.FINE, dfr.getLabel());
}
}
public void hoisted(List<Account> accts) {
Map<String, Schema.SObjectType> types = Schema.getGlobalDescribe();
List<Messaging.SingleEmailMessage> messages = new List<Messaging.SingleEmailMessage>();
for (Account a : accts) {
System.debug(types.size());
}
Messaging.sendEmail(messages);
}
}