At one of my clients we were seeing the occasional spike in memory usage of their portal server. We’ve even seen some of the dreaded OutOfMemoryErrors. Most of the memory growth was natural – due to the growing usage of the portal. The errors are not natural – so something had to be done. At a minimum we needed to layout some guidelines for the developers to follow from hence forward to keep from compounding the problem.
This is a single server environment, no clustering. Over the past couple of years, the technical leadership at the client wanted to focus on speed over memory usage. In general, this meant that instead of re-executing the action phase when a page needed re-rendered, items that were needed for rendering were thrown onto the session. This alone can be considered OK in some circumstances. If the objects are small and few then it’s not that big a deal. But in a portal, almost by definition, there are a lot of applications. So if a lot of applications start throwing objects all over sessions then it can become a problem pretty quickly.
In addition to the times where the objects were small and few, there were times when it was done out of performance necessity. In one instance, searching for items in a Domino ‘archive’ takes over a minute. The fact that this might be fixable some other way aside; this is not something one would want to have happen every time you re-render the page that this portlet sits on. So you store the items on the session. The next question is how many do you store? Do you store the entire result set? Hopefully you limit it to some reasonable size, but reasonable to who?
These are a small subset of what we laid out. Note: These are definitely not specific to portal applications.
- Limit Session Storage
- Minimize information stored on session
- Use hidden variables in forms
- Do not store large collections on the session
- Limit to reasonable size with paging (# per page, alphabetic, date range, etc)
- Limit database result set sizes to smallest usable size.
- If your result sets have more items than the stated threshold, don’t retrieve all of them.
- If your result sets have less items than the stated threshold, don’t retrieve all of them unless you have to
- If you can page through them do that.
- Use reasonable judgment based on the ‘size’ of the objects in the result set.
- If you are building large complex objects for each result, limit to a smaller number stored on session or use design patterns to solve the re-execute issue.
- Use String constants when possible
- For any re-used string values
- Database library, table, and column names that are used more than once
- Use StringBuffers instead of String concatenation always
- Use client side sorting when possible
- Single level sorts
- Relatively small result sets
- Release any session memory by using session.removeAttribute when that data has been consumed and is no longer needed.
- Always cleanup resources, such as database connections, in a finally block to guarantee that they are done.