Tuning performance of a Liferay Portal installation is very different from one client situation to another, and therefore, it is essential to simulate a realistic load and usage distribution, measure various key performance and server metrics, tweak configuration based on observed metrics, and retest to verify that the changes were beneficial. Tuning Liferay performance involves tuning the JVM, base application server, and some Liferay specific parameters, and the following sections discuss some of these tunable settings.
JVM Tuning
Newer installations of Liferay Portal server generally run on a version 1.6 instance of the Java virtual machine; this guide is written with that assumption in mind.
JVM tuning is one of the more complicated areas of portal optimization, mainly due to the fact that custom portlets and applications can have a significant impact on how the JVM manages heap utilization and garbage collection processes. This document is geared towards a stock installation of Liferay Portal with no custom portlets, hooks, or themes deployed. With custom applications running on the application server, it will be necessary to perform additional tuning to the JVM; however, the concepts addressed below will still apply.
Garbage Collection Policies
Generally speaking, when running a server-type application in a JVM, it is a good policy to enable the concurrent-mark-sweep garbage collection policy. The CMS policy essentially modifies garbage collection behavior such that objects are marked and collected from the heap by a thread that runs concurrently to threads servicing application requests; what this means is that pause times caused by major collections against the JVM will occur less frequently and be of shorter duration. Pause times will cause overall performance degradation from the user’s perspective; when a garbage collection run performs a major collection, it will hit a point where it needs to stop execution of all threads in the JVM from running in order to collect dereferenced objects from the heap. The CMS collector performs much of this collection in the background while other threads are operating, thus minimizing the pause time and optimizing the garbage collector behavior to improve throughput. To enable the CMS collection policy and enable parallel remarking of inaccessible objects on the heap, add the following options to the JVM startup arguments:
-XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled
If the decision is made not to enable the concurrent-mark-sweep garbage collection policy, parallel collection of the heap should still be enabled on multi-cpu or multi-core servers. Parallel collection can be enabled by adding the following option to the JVM startup arguments:
-XX:+UseParallelGC
Note:this option should not be enabled if the CMS policy is enabled.
Heap Sizing
Heap sizing is a complicated area, as determining the optimal size for the overall heap and each of the internal segments of the heap is something that is generally driven by application usage and behavior on each specific application server instance; however, there are some general rules of thumb that can be followed to assist in configuring an optimal heap size for the server.
Generally speaking, the following items should be adhered to when sizing the heap:
1. Do not size the young generation to be very large. Anything more than 300MB should be avoided unless detailed analysis of the heap requirements of the application indicates that it will be necessary. The reason for this is that the purpose of the young generation is to segment a small portion of the heap for object creation and storage of short-lived objects. Garbage collection against the young generation happens quite frequently, and increasing the size of the young generation to a larger number will increase the processing requirements of reaping the young generation, which may cause CPU load issues.
2. The best rule of thumb on setting the min and max heap sizes is to set them both to be the same amount in order to prevent heap expansion or contraction. Heap expansion and contraction can in some circumstances provide performance gains due to reduction in complexity of garbage collection runs during off-peak times; however, it also increases the processing complexity of heap management, and can lead to fragmentation of the heap space.
3. The permanent heap will likely need to be increased in size from its default setting for most portal instances. Generally speaking, increasing the permanent heap space to 128M should be adequate for most situations; if you are using applications that make use of dynamic or ad-hoc code generation, however, it may need to be increased further. We have seen scenarios where we had to bump this up to 256M and even 384M. The permanent generation size can be set for the application server instance by specifying the following command-line argument to the JVM:
-XX:MaxPermSize=128M
Application Server Tuning
In addition to JVM tuning, there are other tuning considerations which need to be factored in:
- Thread pool tuning: the application server needs to be configured with the appropriate number and type of threads to handle incoming requests.
- Database connection pool tuning: connection pools used by the Liferay portal instances should be managed by the application server. Connection pool sizing is roughly based on the number of threads accessing database connections.
Tuning these metrics will be highly dependent on your expected traffic, portal usage patterns, and available CPU/memory.
Liferay Tuning
In addition to JVM and standard application server tuning, the following Liferay performance tuning considerations should be taken into account when looking to optimize portal performance:
- Liferay caches: there are various EhCache caches which are maintained by Liferay to store information commonly used by the portal container; tweaking the configuration of these caches can result in a performance gain, depending on cache usage. Additionally, it may be necessary to integrate these caches with a distributed cache management system, such as Terracotta.
- Servlet filters: Liferay makes use of a number of servlet filters, not all of which are necessary for every environment. Some of the commonly disabled filters include the GZip filter, the SSO filters (for specific authentication schemes), and the Sharepoint filter.
- Portlets: Liferay ships with a number of portlets out of the box, not all of which may be necessary for the specific portal environment. Removing unnecessary portlets can improve portal performance.
- Liferay logging: Modifying the logging level of various Liferay components can also have a minor impact on performance.
- Document library file storage: Modifying the underlying Jackrabbit and JCR file storage location can have an impact on some aspects of portal functionality. Standard modifications include altering the out-of-the-box configuration to store JCR and file data in a shared database or filesystem for clustering.
- Search index storage: Modifying the location and implementation of search indexes can also have an impact on portal performance. Potential modifications in this area range from database-backed Lucene modifications to integration with Solr or Terracotta.
Tuning these metrics will be highly dependent on your expected traffic, portal usage patterns, and available CPU/memory.
Scaling and High Availability
Designing an environment which supports both scaling and high availability can provide a unique set of challenges. When designing a high availability environment for Liferay, there are two primary considerations to take into account: system failover and resource utilization. Balancing these two concepts can be highly complex to implement, but once implemented properly, both scalability and failover become trivial to maintain.
Designing for Scalability
Scalable design in this context means that it is possible to make optimal use of all available resources, and it is simple to add additional resources to the environment in order to handle additional load. In order to accomplish this, it is often necessary to employ both horizontal and vertical clustering strategies; vertical clustering provides for a more efficient use of local resources on a per-JVM level, and horizontal clustering provides failover and expandability. The specifics of implementation of both horizontal and vertical cluster members are beyond the scope of this document; however, considerations when implementing clustered application servers which are hosting a Liferay portal environment include the following:
- Configuration of a shared portal database
- Configuration of distributed or shared search indexes
- Configuration of a distributed or shared document library
- Distributed sharing of sessions
- Farm deployment of portlet applications
There are a number of ways to handle each of these items, depending on the specific application server environment and the usage patterns of the portal.
Designing for High Availability
The critical aspect of an architecture which is designed for high availability is a lack of any single points of failure. The user experience should be seamless regardless of a catastrophic failure of any individual system component. The goal is to have multiple nodes in the environment responsible for any individual function, and to have automated failover mechanisms in place to handle routing traffic away from any node that has experienced a failure condition.
Horizontal clustering, as discussed above, provides coverage of this topic for the application server and the Liferay application itself; however, it is critical that other aspects of the system be appropriate addressed in he same fashion. This includes:
- Database servers and database instances
- Authentication servers or services
- Web server frontends
Again, the specifics of designing an environment for high availability are beyond the scope of this document; however, the above should be taken into consideration when planning the overall system architecture.