[SalesForce] APEX Heap size and limit Confusion

Hi So I am trying to understand that what is heap and how it is managed in Salesforce.

What I did is created a VF page and a Http callout class, I have stored a large XML on remote server that I am getting back from my Http callout. Also I have made a custom logging method to capture the max heap that is being used through the Http and XML parsing(by passing Limits.getHeapSize()) which works fine.

My confusion is the number do not match, for instance even for a file as big as 5MB my debug shows Maximum heap size: 0 out of 6000000. and my custom logger shows MAX Allowed : 6000000 | Highest Used Heap : 11929380.

Note: I know that I have used a custom login that capture heap using "Limits.getHeapSize()", so if I see a number example "11929380", shouldn't the code fail as I donot have any try catch.

Code details:
I am using XmlStreamReader to parse the XML.
I am using Transient variable to display the result on screen.

Standard :

enter image description here
Custom VF :

enter image description here
Code:

public class HttpCallout{
public static innerResult callout(String endpoint, String type){
    innerResult rs = new innerResult();
    captureMaxResource(Limits.getHeapSize() , Limits.getCpuTime() , 'before http call' , rs);

    Http h = new Http();
    HttpRequest req = new HttpRequest();
    req.setEndpoint(endpoint); // PDF hosted xml
    req.setMethod(type);        
    HttpResponse res = h.send(req);

    captureMaxResource(Limits.getHeapSize() , Limits.getCpuTime() , 'after http call but before parsing' , rs);

    rs.result = parserXML( res.getBody() , rs);

    captureMaxResource(Limits.getHeapSize() , Limits.getCpuTime() , 'after parsing' , rs);
    return rs;
}

public static string parserXML(String xmlStr , innerResult rs){
    //parsing of XML
    captureMaxResource(Limits.getHeapSize() , Limits.getCpuTime() , 'after xml parsing' , rs);
    return null;
}

public static void captureMaxResource(integer heap , integer cpu , string logindex , innerResult rs){
    if(rs.maxHeap != null && rs.maxHeap < heap){
        rs.maxHeap = heap;
        rs.indexmaxHeap = logindex;
    }
    else{
        rs.maxHeap = heap;
    }

    if(rs.maxCPU != null && rs.maxCPU < cpu){
        rs.maxCPU = cpu ;
    }
    else{
        rs.maxCPU = cpu ;
    }
}

public class innerResult{
    public string indexmaxHeap{get;set;}
    public integer maxHeap{get;set;}
    public integer maxCPU{get;set;}
    public string result{get;set;}
}
}

Best Answer

As I discovered when investigating Does execute anonymous from Developer Console not enforce heap size limit?

The support rep responding to my case told me:

heap size checks are performed according to certain heuristics, meaning they are not performed on evaluating each statement, and as a result it is possible to exceed the limit, but this will be enforced as soon as salesforce checks it.

Also note that they will not share the specifics of when it will be checked:

I had a discussion with my seniors regarding the evaluation of heap size as how it works internally but the architecture and internal implementation details cannot be shared.

As explained previously we follow certain heuristics to determine when to compute the heap size (which performs a heap walk), and when to enforce the max heap size, which doesn't occur when invoking Limits.getHeapSize().

Related Topic