Debugging heap size - what's happening on the server?

  • 2
  • Question
  • Updated 3 years ago
  • Answered
This is not a "I'm getting a heap size error, help!" post - I know about this issue, but I'm trying to get an deeper understanding of the causes.

I have a page that can end up showing a lot of rows in a table after a button is pressed and a model gets queried. There aren't any body fields returned in the model, it's about 30 fields that are dates, strings, etc.

I've reached a point with the page where I'm getting Apex heap issues. I've been able to handle these in the past with a few tricks - but I'm all out of tricks.

I'm a bit confused because, if I take the SOQL query as per the model in the debug log, plug it in to the developer console and check the heap size there, the heap size is about 1MB. What happens on the server that causes an increase in size by such an amount? I'm not questioning the Skuid's technical capability - far from it, I'm sure there are reasons for it. But I am curious as to why this happens. I've had similar things happen in the past where literally including one extra record will cause an extra 2 MB on the heap size, though this was on an old release...

Whilst I'm asking - what's the best way to debug such problems? I need to sit with the Salesforce debug docs for a while and read up on it (especially after Winter 16, whose changes don't seem intuitive at all...), but I'm struggling to get useful information about how Skuid is using up limits. In my example above, the button click causes a VF remote call; having debugging on the user captures a log, but no matter what settings I use, I never seem to get the limits summary report. How do people use the debug logs with Skuid?
Photo of Gary

Gary

  • 1,518 Points 1k badge 2x thumb

Posted 3 years ago

  • 2
Photo of Ben Hubbard

Ben Hubbard, Employee

  • 12,490 Points 10k badge 2x thumb
Hi Gary,

This is a really good question. Sorry it's taken us so long to get to it. To fully understand this, we need to dive into what exactly goes into the heap when you load up a Skuid page. While there are many small things that go into the heap, I'll cover just the major items.

1. Data from your models
For each of your models with the "Load Model data on page load" checkbox checked and the "Process Model client-side" checkbox unchecked, the results of this query are serialized into JSON and added to the heap. In Salesforce, when you serialize a list of SObjects, it actually contains quite a bit of extra information on each record, like its REST url and its SObject type.

2. Metadata from your models
This isn't obvious, but Skuid actually pulls in quite a bit of metadata for each of your models. This is quite often more expensive to your heap allotment than the actual data. This includes information about each field in your model, and information about the sobject that this model is based on. Polymorphic reference fields are the worst offenders as we need to know which objects each field is allowed to be reference. (This can sometimes be almost every object in our org!) Other offenders are picklist fields. We need to know about each picklist option and any dependency information about those picklists.

3. Your Skuid Page XML
The actual Skuid page XML document (minus a few sections) is sent to the browser and counts against your heap as well. This includes any inline snippets, javascript resources, or css resources that you've included in your page.

These are the 3 major areas that contribute to your page's heap size. Next I'll go over a few suggestions for limiting this, some you've already mentioned, but I'll go over them for completeness.

1. Move large and medium sized inline resources to a separate static resource.
Inline resources contained in your page XML are a convenience for small snippets of javascript or css. As soon as you start doing some extensive customization, switch to using static resources to store this code.

2. Don't put fields in your model unless you need them for your page.
I've seen many Skuid pages with fields included in models that are never used. Especially check picklists and polymorphic fields on standard objects and verify that they are needed.

3. Don't put fields of type "BASE64" into your Skuid models.
This is typically fields like "Body" on the Attachment object.

4. Use the "Max number of Records" property.
This limits the number of records that a particular model pulls in on page load. Only pull in what the user needs right away. You can load more data into the model later.

5. Models that are exclusively used for the calendar component should have the "Load Model data on page load" checkbox unchecked.
Since the calendar component automatically filters models down based on a date range, and loads in data when needed, you don't need to load in data for calendar models on page load.

If you've done all this and you're still running into issues with heap size, there are a few more advanced techniques to try. These methods are not always preferred across the board, but in many situations they are a good idea.

1. Check the "Process model client-side" checkbox.
This will cause the model to be ignored during the initial load of the page. Once the skuid page is loaded, it will then go back to the Salesforce server and load client-side models. On this second trip to Salesforce, you get a new set of limits.

2. Use page includes.
When Page Includes are loaded they are in a new transaction context so they get a new set of limits as well. Sometimes, especially for pages that utilize the Tabset component, you can put each of your tabs in its own Page Include. It is important to remember that page includes must use different model names than the page that included them or there will be conflicts.

I'm sure there are some other methods that I've missed here, but this should get you started.
Photo of Gary

Gary

  • 1,518 Points 1k badge 2x thumb
(Repost as my original post got swallowed up upon submit...)

Ben, thanks for taking the time to write that response - it was both useful and interesting :) I know there's a "Making pages load fast" entry in the documentation, but what I like about your response is that it goes into more detail about what happens, not just things to try. In short - I think your reply should be part of the documentation :)

And along those lines, I think it'd be great to know more about what Skuid is doing at this level - it helps us with reasoning about what's going on when a page is not behaving as expected. As I hinted in my original post, Salesforce's debug logs aren't always great - as I was getting a "Heap Limit" error, the debug logs were saying that no heap space was being used at all in the skuid namespace.  ̄\_(ツ)_/ ̄

Ben, just to extend your post to when querying (or re-querying) a model as an action, not on page load - I guess the explanation stands, with the exception of the loading of the skuid page xml, and the static resources? Are there any other differences of note?