You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 22 Next »

Tapestry has a great performance story to tell. It's designed to take advantage of the speed of the modern JVM: no reflection, built to support a high level of concurrency without contention, and clean, lightweight code paths. In addition, there is built-in integrated GZIP content compression, far-future expires headers on static resources, JavaScript aggregation and minification, and an intentionally lightweight use of the HTTPSession. The result is a blistering fast framework. See Tapestry's Performance Tested for some objective numbers.

float:rightRelated Articlesaui-labelfalsefalseRelated Articleslabel = "persistence" and space = currentSpace()

Performance Tips

But even with all of Tapestry's built-in speediness, to really get top performance you'll need to be sure you're not hamstringing Tapestry. As a start, use the following checklist:

  • Ensure (be absolutely sure) that Production Mode is turned on in production.
  • Minimize the use of the HTTPSession (see below), especially if you're using clustering.
  • Set tapestry.clustered-sessions to "false" if you aren't using clustering.
  • Organize your JavaScript files into JavaScriptStacks.
  • Ensure that your static resources (images, CSS, JavaScript) are being cached by the browser.
    • Use "asset:" or "context:" binding prefixes for all links to static resources (images, CSS, JavaScript).
    • Make sure that your firewall, proxy server, load balancer, front-end web servers, and app servers all allow caching of static resources.
    • Ensure "cache-control" and "vary" HTTP headers are set correctly for your static resources.
    • Use a client-based tool (like Firebug) to examine the requests that your browser makes as you navigate through the site. You should not see repeated requests for static resources.
  • Consider using a Content Delivery Network for static parts of your site.

After all of the above issues are addressed, if you still have performance problems, they probably aren't related to Tapestry.

Clustering versus Sticky Sessions

For web applications, clustering is a load-balancing technique in which multiple application servers are set up to behave as one big server. Generally this requires replicating HttpSession data across the servers, to ensure that a user's web interactions will continue without interruption regardless of which server handles the next request. Session replication achieves very high reliability, but it incurs an extra performance cost (due to the serializing and deserializing of session data and the extra network traffic required).

In contrast, Sticky Sessions (also called session persistence or sticky persistence) is a load balancing technique in which each session is assigned to a particular server for the duration of the session. This approach doesn't require copying HTTPSession data between servers, so it's very scalable. But if a server goes down, all of its sessions are lost.

In general, the sticky sessions approach is the way to go when possible (that is, when performance is more important than session survival). It represents a much more efficient use of resources ... you are scaling out not up, which is always cheaper. It also means that you don't have to be as careful about what goes into the HTTPSession.

For details on setting up clustering and sticky sessions, see the documentation of whatever load balancer you are using.

Clustering

Tapestry is designed to be "a good citizen" of an application server that supports clustering. It is careful about what it writes into the HttpSession. The framework understands that the server that receives a request may not be the same one that rendered the page initially; this knowledge affects many code paths, and it guides the approach Tapestry takes to caching page and component properties.

Your part is to properly manage the objects put into the HttpSession (via @SessionAttribute, @SessionState or @Persist; see Session Storage):

  • Don't store anything in the session that you don't have to. Principally this means minimizing the use of @Persist (see Page Activation and Using Select With a List), storing only IDs in the session rather than whole entities.
  • Where possible, persist only objects that are immutable (i.e., String, or a primitive or wrapper type).
  • Only put serializable objects into the session.
  • Make use of the @ImmutableSessionPersistedObject annotation and OptimizedSessionPersistedObject interface (both described below).

Again, Tapestry is a good citizen, but from the application server's point of view, it's just another servlet application. The heavy lifting here is application server specific.

Clustering Issues

  • No labels