- Performing in the Cloud
- Measuring the Cost of Class Loading
- Avoiding Cold Startups
- Improving Performance in General
- Summary
Improving Performance in General
The subtitle of this book is Building High-Performance Java Apps with Google App Engine because this book focuses on performance optimization more than do other books. This section provides a general overview of possibilities for performance optimization.
Optimizing Your Data Model for Performance
If you model your data for the App Engine datastore the same way you model your data for a relational database, you can be certain that you will run into performance problems at some point. The way the App Engine datastore divides data over multiple machines in the cloud is fundamentally different from the way a relational database stores data on disk. In many cases, you need to do the exact opposite of what you are used to doing. For example, you need to denormalize your data instead of normalizing it.
Because you can store arrays of data, there is less need of relationships between tables, although you should be cautious if you feel the need to index the array, because the size of your total index may explode.
You should consider the need for transactions before you set up your data model. Transactions require entity groups, and larger entity groups may harm scalability.
Chapter 4, “Data Modeling for the Google App Engine Datastore,” presents a detailed discussion of datastore characteristics. Using the APIs is demonstrated in Chapter 10, “Storing Data in the Datastore and Blobstore.”
Avoiding Redundant Processing Using Cache
Many time-consuming tasks are done repeatedly for subsequent requests—think of tasks that require gathering data or processing intensive calculations. The same processing might be repeated for a single visitor or for multiple visitors.
Proper caching can help avoid repetitive processes. This book explains both fine-grained caching using memcache and page-level caching on the Internet. See Chapter 14, “Optimizing Performance Using the Memory Cache,” for in-depth information.
Postponing Long-Running Tasks Using the Task Queue
In many cases, high responsiveness is more important than high performance. Responding quickly to a visitor’s request can sometimes be done by postponing the actual work. As long as the visitor can trust that the work will be done eventually, he or she will be pleased with the quick response.
The Task Queue API can be used in multiple ways. You can preschedule tasks at regular intervals, or you can post tasks to the queue on demand. Both methods can help improve performance and responsiveness.
Details on Task Queue are discussed in Chapter 12, “Running Background Work with the Task Queue API and Cron.”
Improving Page Load Performance in the Browser
A high-performing server is practically useless if the page loading in the browser ruins the total response time. For example, if your HTML is full of useless elements, classes, and IDs, your Cascading Style Sheet (CSS) file beats the size of an average phone book, and you reach a megabyte of JavaScript files, all server-side efforts are lost. You could make it even worse by adding one or more Flash files in your page. But then you are clearly working in the wrong direction.
With HTML5 and CSS3, you hardly need Flash anymore except, perhaps, for an incidental video player being used until HTML5 videos are sufficiently mature. The newly added elements in HTML5 may help you downsize your CSS files. The less specific your CSS file, the easier it is to maintain.
The way you load your JavaScript has a large impact on the page load time. Loading JavaScript unobtrusively at the bottom of the page allows the rest of the page to render before the JavaScript is interpreted. This improves the responsiveness to the visitor.
Part III, “User Interface Design Essentials,” covers HTML5, CSS3, JavaScript, and AJAX, providing details on browser optimization from a technical perspective.
Working with Asynchronous APIs
Page loading generally does not entail heavy data processing. Mostly it consists of waiting for services such as the datastore to respond. If you know in advance that you need to make multiple backend requests and the backend requests are independent of each other, you can work with asynchronous APIs.
One of the most important asynchronous APIs is described in Chapter 10, “Storing Data in the Datastore and Blobstore.”
Optimizing Your Application before Deployment
Some performance optimizations are a result of planning and designing. The more effective performance improvements usually result from careful experimentation and measurements.
You can profile calls to Google’s backend services using AppStats. Most of the overhead in an average App Engine application is in the backend calls. If you do a lot of heavy lifting in your own code, you are encouraged to profile this code and optimize where possible.
AppStats is explained in Chapter 19, “Assuring Quality Using Measuring Tools.”