A stack is a place in the computer memory where all the variables that are declared and initialized before runtime are stored. The heap is the section of computer memory where all the variables created or initialized at runtime are stored. On the other hand, the heap is an area of memory used for dynamic memory allocation.
When you create objects in Apex code memory is allocated to store the objects. And that memory is allocated from the allocated heap. Think of it as a designated amount of memory you can use up in your Apex request.
Heap play an important role when your application runs, Bad code quality can consume the heap size badly and which impact the performance of your application
As you know heap is important to allocate the memory at runtime and hence we should be very careful while writing the code and must ensure to take care of heap size. If the heap size is huge, it will surely impact the performance of the application and the application will get slow.
Salesforce enforces an Apex Heap Size Limit of 6MB for synchronous transactions and 12MB for asynchronous transactions.
The "Apex heap size too large" error occurs when too much data is being stored in memory during processing. The limit depends on the type of execution (E.g. synchronous vs asynchronous calls) and the current value can be found in the Apex Developer's Guide.
It is important to review your code and follow best practices to ensure that the heap limit does not exceed the maximum. The below example shows the incorrect use of collections.
The List baseList, the value of SampleMap and the List tempList are pointing to the same memory address. As a result, the heap size doubles with each iteration of the loop.
public class HealsizeExample{
public static void testHeapSize(){
String str = 'aaaaa bbbbb ccccc ddddd eeeeee fffff hhhhh jjjjj kkkkk lllll mmmmm';
List<String> baseList = str.split(' ');
System.debug('This is baseList :'+baseList);
System.debug('This is baseList :'+baseList.size());
List<String> bigList = baseList;
system.debug('This is bigList :'+bigList);
System.debug('This is bigList :'+bigList.size());
Map<integer, List<String>> SampleMap = new Map<integer, List<String>>();
SampleMap.put(1, bigList);
system.debug('This is SampleMap :'+SampleMap);
System.debug('This is SampleMap :'+SampleMap.size());
for (integer i=0; i<50; i++) {
List<String> tempList = new List<String>();
tempList = SampleMap.get(1);
bigList.addAll(tempList);
}
system.debug('FINAL LIST SIZE IS '+bigList.size());
}
}
Solution-
public class heapCheckSuccess{
public static void myHeapTest(){
String tStr = 'aaaaa bbbbb ccccc ddddd eeeeee fffff ggggg 11111 22222 33333 44444';
List<String> baseList = tStr.split(' ');
Map<integer, List<String>> Sample = new Map<integer, List<String>>();
List<String> bigList = baseList;
Sample.put(1, bigList);
List<string> myList = new list<string>(); //Declare a new list
for (integer i=0; i<50; i++) {
List<String> tempList = new List<String>();
tempList = Sample.get(1);
system.debug('templist: ' + tempList.size());
system.debug(' bigList: ' + bigList.size());
myList.addall(tempList); //original code is bigList.addall(tempList);
}
system.debug('FINAL LIST SIZE OF bigList IS '+ bigList.size());
system.debug('myList IS '+mylist.size());
}
}
Best Practices to avoid Heap Size
Use the Transient Keyword
Try using the "Transient" keyword with variables in your controllers and extensions. The transient keyword is used to declare instance variables that cannot be saved, and shouldn't be transmitted as part of the view state for a Visualforce page.
Use Limit Methods
Use heap limits methods in your Apex code to monitor/manage the heap during execution.
Limits.getHeapSize() - Returns the approximate amount of memory (in bytes) that has been used for the heap in the current context.
Limits.getLimitHeapSize() - Returns the total amount of memory (in bytes) that can be used for the heap in the current context.
Fetch only necessary Fields in the SOQL Query
If the objects in your collection contain related objects (i.e., Account objects with a number of related Contacts for each) make sure the related objects only contain the fields that are actually needed by your script.
Use SOQL For Loops
To avoid heap size limits, developers should always use a SOQL "for" loop to process query results that return many records. SOQL "for" loops retrieve all sObjects in a query and process multiple batches of records through the use of internal calls to query and queryMore.
Issue
List accs = [SELECT Id, Name FROM Account];
for(Account a : accs){
System.debug(a.Name);
}
List accs = [SELECT Id, Name FROM Account];
for(Account a : accs){
System.debug(a.Name);
}
Solution
for(Account a : [SELECT Id, Name FROM Account]){
System.debug(a.Name);
}
for(Account a : [SELECT Id, Name FROM Account]){
System.debug(a.Name);
}
Switching to Batch Apex increased the heap limit to 12000000 bytes. Also, by setting the scope to 1 only one attachment was processed at a time.
- Don't use class-level variables to store a large amount of data.
Run Future Methods with Higher Limits (Pilot)
@future(limits='2xHeap')
public static void myFutureMethod() {
// Your code here
}
No comments:
Post a Comment