Performance Tuning Spring Applications
The Spring programming and configuration models are well understood and documented and used by hundreds of thousands of developers worldwide. This white paper was written for operations teams who manage those applications.The first part of the white paper reviews the core responsibilities of the Spring kernel, these are:
- Bootstrapping - creates an application context that provides the runtime context for an application.
- Determining component configuration - determines which application components need to be created, how they are configured, and what supporting services they require. This step is also know as the blueprint stage, as service readiness is determined.
- Instantiation, Configuration, and Assembly - using the blueprint, components can now be constructed when needed. This stage is paramount, as Spring needs to take into account dependencies between components, specific ordering, and construction mechanisms. Failures at this stage will leave the application inoperable.
- Component Post Processing - components that are registered as post processors by Spring enterprise services and user servers are invoked.
- Decoration - when cross cutting component behavior is specified, declaratively as aspects using the AOP namespace or annotated classes, the Spring kernel has additional tasks. The specified pointcuts need to be qualified and a proxy generated for the original component in order to decorate the component with the additional functionality.
- Managing component life cycle and scope - as components may have different life cycles and scope, the Spring kernel continues to oversee creating, re-using, and destroying components.
Optimizations then fall into two major categories: establishing an effective blueprint (tuning your configuration), and making effective use of runtime facilities (optimizing your application design). Start off with the cleanest and clearest design, making full use of the facilities that Spring offers, and only deviate from this where the numbers show real benefit.Establishing an effective blueprint
To establish an effective blueprint, you need to take advantage of your deployment platform, and keep environmental dependencies out of the Spring configuration. This is especially important when declaring database connectivity and JMS connections, where utilizing JNDI enables you to take full advantage of your deployment platform facilities. Other advise provided is:
Using Spring's PropertyPlaceholderConfigurer is excellent for externalizing configuration settings that may need to be changed by an operations team.and
A good tip here is to use Spring's JMX export capabilities to define an MBean that exposes all of the configuration values via JMX. This enables you to connect to a running application and easily see the configuration values it is currently using.Taking advantage of runtime optimizations
Many runtime production performance issues are tracked down to the persistence layer, and having a properly optimized database and data access layer is of utmost importance.
- Strive for the right balance between eager and lazy loading strategies
- Show the SQL statements in the logs
- For batch style operations, bulk updates, or inserts, and stored procedures it's normally best to use JDBC (via Spring JDBC) than an ORM tool
- Make the most of the features that your database offers
- If you have an operation that contains entirely persistence logic (no business logic), consider moving it into the database as a stored procedure and invoke it via Spring JDBC
- Read-only reference data can be kept in a cache in memory
- The retry support in the Spring Batch project can be used to retry failing operations (for example, an operation that has failed on an individual cluster node in an Oracle RAC). This can ease the operational burden by reducing the number of failures that bubble up to end users.
- Don't underestimate the cost of web content rendering. You definitely want to do this outside of a transaction.
- Don't instantiate an application context per-request (a mistake sometimes encountered when teams migrate legacy applications to Spring).
- Consider exploiting Spring's asynchronous task executors to reduce user wait time for tasks that can be run in the background.
- Choose an appropriate remoting protocol. If you don't need SOAP interoperability, a simple scheme such as Spring's HttpInvoker support will be simpler and faster.
- Consider using AspectJ in place of Spring AOP for aspects that impact large portions of your application.
The complete white paper can be download from SpringSource.
Mike Hartington Jul 26, 2015