I'm getting Apex head size limit while manipulating string.
Here is my example :
ContentVersion cv = [SELECT Id, VersionData, PathOnClient FROM ContentVersion WHERE Id = '0685r000001z4GvAAI']; // 0685r000001z4MUAAY
Blob versionData = cv.VersionData; // 2Mo (2_358_962)
String message = EncodingUtil.base64Encode(versionData);
System.debug('0. '+Limits.getHeapSize());
for (Integer i = 0; i < 100; i++) {
message = message.substring(0, message.length() - 1);
System.debug((i + 1) + '. ' + Limits.getHeapSize());
}
And here is the output :
18:56:15.28 (28532912)|EXECUTION_STARTED
18:56:15.28 (28540661)|CODE_UNIT_STARTED|[EXTERNAL]|execute_anonymous_apex
18:56:15.28 (30052994)|USER_DEBUG|[2]|DEBUG|1. 1065
18:56:15.28 (156834306)|USER_DEBUG|[31]|DEBUG|versionData.size() : 2358962
18:56:15.28 (202193484)|USER_DEBUG|[33]|DEBUG|0. 3146520
18:56:15.28 (203894050)|USER_DEBUG|[36]|DEBUG|1. 3146531
18:56:15.28 (205469272)|USER_DEBUG|[36]|DEBUG|2. 3146530
...
18:56:15.28 (215428836)|USER_DEBUG|[36]|DEBUG|9. 3146523
18:56:15.28 (217021878)|USER_DEBUG|[36]|DEBUG|10. 3146523
18:56:15.28 (218687727)|USER_DEBUG|[36]|DEBUG|11. 3146522
...
18:56:15.28 (223537621)|USER_DEBUG|[36]|DEBUG|14. 3146519
18:56:15.28 (226547176)|EXCEPTION_THROWN|[EXTERNAL]|System.LimitException: Apex heap size too large: 6291784
18:56:15.28 (226831485)|FATAL_ERROR|System.LimitException: Apex heap size too large: 6291784
How it is possible ?
Do you have any idea about that ?
Thank you
@Cheick Sissoko in Apex, strings are immutable, which means that every time you modify a string, a new copy of the string is created in memory. In your example, you are creating a new copy of the string 100 times in a loop, which causes the heap size to increase rapidly.
To avoid this issue, you can use a StringBuilder object instead of a string. The StringBuilder object is mutable, which means that you can modify the contents of the object without creating new copies in memory.
Here is an example of how you can use a StringBuilder object to modify the base64-encoded string:
ContentVersion cv = [SELECT Id, VersionData, PathOnClient FROM ContentVersion WHERE Id = '0685r000001z4GvAAI'];
Blob versionData = cv.VersionData;
String message = EncodingUtil.base64Encode(versionData);
System.debug('0. '+Limits.getHeapSize());
StringBuilder sb = new StringBuilder(message);
for (Integer i = 0; i < 100; i++) {
sb.deleteCharAt(sb.length() - 1);
System.debug((i + 1) + '. ' + Limits.getHeapSize());
}
message = sb.toString();
Using a StringBuilder object in this way should help you avoid hitting the heap size limit.