Why is Schema.describeSObjects(types) Slower Than Schema.getGlobalDescribe()?

I was about to reconfigure some of my code to use the newer Schema.describeSObjects(types) method that I had heard was faster than using a globalDescribe.

I made some code to quickly check this and I was dismayed to find that the newer technique is not only not faster, it’s about twice as slow as using a global describe. Here’s the code I used :

New DescribeSObjects() method

//each block was run separately for timing purposes
String obj = 'Account';
String[] types = new String[]{obj};
System.debug('START DESCRIBE SOBJECTS');

for (Integer i = 0; i < 50; i++) {
  List<Schema.DescribeSobjectResult> results = Schema.describeSObjects(types); 
}
System.debug('FINISH DESCRIBE SOBJECTS');

Old getGlobalDescribe() method

String obj1 = 'Account';
System.debug('START DESCRIBE GLOBAL');

for (Integer i = 0; i < 50; i++) {

  Map<String,Schema.SObjectType> gd = Schema.getGlobalDescribe(); 
  Schema.SObjectType sobjType = gd.get(obj1); 
  Schema.DescribeSObjectResult describeResult = sobjType.getDescribe(); 
}
System.debug('FINISH DESCRIBE GLOBAL');

Over 5 runs of each, the getGlobalDescribe() method took an average of 337ms for 50 describes and the describeSObjects() method took and average of 658ms. This is basically twice as long.

Does anyone have any insight as to why this would be? Any improvements that will significantly improve the accuracy of the resulting data?

As this data stands, I’m sticking with the old method.

One final note: the old technique uses 3 times a much heap (67kb vs 27kb)

Answer

I suspect, internally, that this code is written in Apex Code and thus suffers the same general performance problems as doing it yourself. If you want a blazing-fast interface, consider using Type instead:

String obj1 = 'Account';
Long time1 = DateTime.now().getTime();

for (Integer i = 0; i < 50; i++) {
    SObjectType r = ((SObject)Type.forName('Schema',obj1).newInstance()).getSObjectType();
    DescribeSObjectResult d = r.getDescribe();
}
Long time2 = DateTime.now().getTime();
System.debug(time2-time1);

This runs in about 10-15ms for 50 describes, while Schema.describeSObjects runs in about 1700-1900ms in my org, and Schema.getGlobalDescribe runs in 300-500ms in my org.

Skipping the global describe shaves off an amazing amount of time. Caching is also acceptable; if you must use Schema.getGlobalDescribe, use it only once to avoid performance issues:

String obj1 = 'Account';
Long time1 = DateTime.now().getTime();

Map<String,Schema.SObjectType> gd = Schema.getGlobalDescribe(); 

for (Integer i = 0; i < 50; i++) {
    Schema.SObjectType sobjType = gd.get(obj1); 
    Schema.DescribeSObjectResult describeResult = sobjType.getDescribe(); 
}
Long time2 = DateTime.now().getTime();
System.debug(time2-time1);

This results in a more respectable time of about 80-140ms instead.

I personally have a static variable that all classes use so I never global describe more than once per transaction:

public static Map<String, SObjectType> globalDescribe {
    get { if(globalDescribe == null) globalDescribe = Schema.getGlobalDescribe();
        return globalDescribe;
    }
}

If it’s never used, there’s no performance penalty, but when I do need it, I will only need to global describe once.

Attribution
Source : Link , Question Author : Caspar Harmer , Answer Author : sfdcfox

Leave a Comment