[SalesForce] Does execute anonymous from Developer Console not enforce heap size limit

I have been investigating a potential heap size problem in our production code, and I wanted to recreate some simple elements through the developer console.

To cause a heap size exception, I would select every standard field from account for 50,000 accounts into a list.

System.debug('Heap size before query = ' + Limits.getHeapSize() + ', out of maximum ' + Limits.getLimitHeapSize());
List<Account> accs = [select AccountNumber, AccountSource, AnnualRevenue, BillingCity, BillingCountry, BillingPostalCode, BillingState, BillingStreet,
                             CreatedById, CreatedDate, CurrencyIsoCode, Description, Fax, FirstName, Id, Industry, IsCustomerPortal,
                             IsDeleted, IsPersonAccount, Jigsaw, JigsawCompanyId, LastActivityDate, LastModifiedById, LastModifiedDate, LastName,
                             MasterRecordId, Name, NumberOfEmployees, OwnerId, Ownership, ParentId, PersonBirthdate, PersonContactId, PersonEmail,
                             PersonEmailBouncedDate, PersonEmailBouncedReason, PersonHomePhone, PersonLastCURequestDate, PersonLastCUUpdateDate, PersonLeadSource,
                             PersonMailingCity, PersonMailingCountry, PersonMailingPostalCode, PersonMailingState, PersonMailingStreet, PersonMobilePhone, PersonOtherCity,
                             PersonOtherCountry, PersonOtherPostalCode, PersonOtherState, PersonOtherStreet, PersonTitle, Phone, Rating, RecordTypeId, Salutation, ShippingCity,
                             ShippingCountry, ShippingPostalCode, ShippingState, ShippingStreet, Sic, SicDesc, Site, SystemModstamp, TickerSymbol, Type, Website
                      from account
                      limit 50000];
System.debug('Heap size after query = ' + Limits.getHeapSize() + ', out of maximum ' + Limits.getLimitHeapSize());

This is a full copy sandbox and there are over 50,000 accounts.
My expectation was that this would fail with a heap size limit exception.

Instead I get the output:

USER_DEBUG [1]|DEBUG|Heap size before query = 1069, out of maximum 6000000
USER_DEBUG [12]|DEBUG|Heap size after query = 33931975, out of maximum 6000000

Notice the heap size used is 34MB and the limit 6MB but no exception occurs. I have done some more experiments and I can iterate over the list and carry on executing code with the heap size above this level.

Here are the limit usage stats which seem to show 0 heap usage.

Limit stats for execute anonymous

I can't find anywhere that this is expected behaviour for the developer console. My understanding was that the limits apply in all contexts.

Can anyone shed any light on this?

Best Answer

So I logged a case with support (Case Number 14444735) to find out if this limit has actually been lifted, and here's the response I got:

I have verified in Execute Anonymous and the heap limit is lifted extremely. I am currently investigating as why the execute anonymous from Developer Console does not enforce heap size limit. I will provide you with an update as soon as possible.

And some time later:

I have discussed the issue with my seniors and found that 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.

At that point, I asked for more detail and if there is any plan to change this behavior. He came back with:

As of now we have to [sic] information that R&D team is planning to make any changes to this. But currently the heap limit would cause a crash whenever system checks for it.

You can also get more details regarding this from the below mentioned URL: https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_gov_limits.htm

I also asked why Limits.getHeapSize() does not count as checking the limit, and he refused to further explain:

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().