Schema describe call inside a loop
ID |
apex.performance.eager_describe |
Severity |
info |
Remediation Complexity |
medium |
Remediation Risk |
low |
Remediation Effort |
medium |
Resource |
Performance |
Language |
Apex |
Rationale
A describe call is not free: the platform builds the metadata result on demand, and getGlobalDescribe() builds one for every object in the org. Inside a loop that cost is paid per iteration, in CPU time that counts toward the 10-second synchronous limit - and the result is identical every time, because object metadata cannot change during a transaction. The loop that runs over five records in a test runs over two hundred in a trigger, which is where the CPU time limit exceeded arrives, with no line number pointing at the describe.
The following code illustrates the pattern detected by this rule:
public class FieldWalker {
public void describeInLoop(List<String> objectNames) {
for (String name : objectNames) {
// FLAGGED: Schema describe call inside a loop
Map<String, Schema.SObjectField> fields = Schema.getGlobalDescribe().get(name).getDescribe().fields.getMap();
System.debug(fields.size());
}
}
public void describePerField(List<String> fieldNames) {
for (Integer i = 0; i < fieldNames.size(); i++) {
// FLAGGED: Schema describe call inside a loop
Schema.DescribeFieldResult f = Account.SObjectType.getDescribe().fields.getMap().get(fieldNames[i]).getDescribe();
System.debug(f.getLabel());
}
}
public void describeOnce(List<String> fieldNames) {
Map<String, Schema.SObjectField> fields = Account.SObjectType.getDescribe().fields.getMap();
for (String name : fieldNames) {
System.debug(fields.get(name));
}
}
public void noDescribe(List<Account> accounts) {
for (Account a : accounts) {
System.debug(a.Name);
}
}
}