Previous Table of Contents Next


Of these, the first two can often be solved by pooling resources, or caching. For example, a servlet can share database connections between requests, assuming that there is no security reason not to. In this case, only the init method suffers the performance hit of making a connection. However, sharing connections and keeping them open uses resources. On large Web servers, it is important to consider the effects of holding resources, as much as it is to consider the time it takes to keep reconnecting. It may also be possible to cache the results of database or other queries. In this case, only the first query requires network access, while the others just access data in memory.

Along the same lines, files can be cached in memory. Although this seems like overkill at first, it can increase performance dramatically. However, it does require memory, and the total memory usage of the servlet should be considered before caching lots of files. Regardless of caching, always use buffered readers or streams to read and write files. This can improve performance 5 to 10 times, in some cases.

One of the advantages of servlets over other server plug-in technologies like NSAPI or ISAPI is that they run inside the virtual machine and are subject to garbage collection. This means, in one sense, that you don’t have to worry about memory. However, the reality is that creating objects takes time, and a servlet that creates a lot of objects will reflect that time usage in its performance. There are several ways to deal with the allocation issue. First, keep in mind that you should write simple code first. Don’t try to avoid memory allocation issues before you even test the program the first time. Second, avoid simple allocations issues by:

1.  Using StringBuffers to create large strings rather than appending strings together. This will ensure that only one buffer is used to create the result.
2.  Reusing objects when possible rather than creating new ones.
3.  Avoid using Sessions unless they are necessary.
4.  Avoiding the creation of immutable objects, like Strings, for data that has to change. This is especially true in your own libraries.

Third, set object references to null when you are done with the object to ensure its availability to the garbage collector. Finally, the next generations of virtual machines, including Sun’s HotSpot, are designed to reduce the overhead of creating a lot of temporary objects. If you have good code that needs to make a bunch of objects, look into trying a different VM and see if that improves performance sufficiently.

Algorithms represent the foundation of your servlet or any program. In many cases, you will not be using the classic algorithms like sorting or searching, but your servlet will rely on some form of recipe for performing its job. The hard part of tuning your algorithms is the desire to tune them too early. Always use the simplest algorithm first. If testing shows a problem and you can associate the performance problem with the algorithm, it is worth improving.

Extending this discussion to code in general, write simple, solid, maintainable code first. Experience has shown that your performance bottleneck will probably be in less than 10 percent of that code, so don’t try to optimize the whole thing. Instead, try to find the key performance issues, then rewrite that code, if necessary, to use fancier and faster techniques.

As always, the fastest code is the code you don’t write. Small, targeted servlets can be much faster, once you deal with any network/file issues, than an equivalent large, multipurpose servlet. In the same vein, the fastest servlet is the one you don’t have to write. Basically, this means that you should let the Web server do its job whenever possible. In particular, Web servers are great at sending files to the user. Don’t write a servlet to do the same thing unless you are adding value to the process. A good example of this would be a site with an online catalog. Let’s say the catalog changes once a day. Instead of using servlets to dynamically display the data from the database for each request, you could rebuild the HTML pages once a day, and have the Web server serve the HTML directly from disk. Basically, if the data for a Web page is not customized on every request, try to cache it to disk and let the Web server do its job, rather than programmatically creating HTML each time.

To conclude the discussion on performance, we should at least mention the hardware vendor’s motto for performance: more memory, faster CPU, bigger computers, spend money. Basically, you may have good code, but the demand has outstripped the platform you run it on. For Java, this platform extends beyond the hardware into the virtual machine. From an objective point of view, there are a number of things to try, not all of which cost money:

  Compiler options; use optimization when possible
  New compiler
  New virtual machine
  New servlet host (Web server/application server)
  More memory
  Different network cards
  New OS or new network drivers
  New hardware

Certainly you may be constrained to maintain the existing version of any of these items, but keep them in mind when tuning performance.

As always, performance tuning is a hard process and very application specific. The most important rule is always to measure before you tune. If you don’t measure, you can spend a lot of time on parts of the code that don’t really affect performance one way or the other.

Summary

Servlets represent a powerful mechanism for extending a Web server’s functionality and implementing the server portion of a servlet/applet pair or a Web application. As with all client/server programming, there are important performance and design issues to consider:

  Minimize the time required to perform each service request. This often means providing several servlets, one for each request type in an application.
  If possible, support multiple threads. This will allow the most flexibility and, on a multiprocessor computer, may allow you to take advantage of multiple processors. However, you will need to protect shared resources with locks and/or isolation.
  Keep security in mind. Servlets are run on your computer and should not be programmed to execute the client’s whims, but your own well-planned actions.
  Measure performance before tuning in a situation that is as realistic as possible. Use tools allowing you to test the servlet under a real-world request load.
  Use the DebugLog or some other tool to implement debugging code early on. Even in writing this book, we relied on the DebugLog to find errors. In most cases, we removed the debugging code to make the example easier to read, but in the larger examples in later chapters, this code was left in to show how it could be used to find errors.
  Rely on the Web server to do its job. Don’t write servlets because you can, write them because you need the dynamic output that they provide.
  Use HTTP servlets when you can. This will provide an easier implementation framework, and the request and response objects will provide more information than the generic equivalents.

The next chapter focuses on a larger servlet-based application. Following chapters cover JavaServer pages. These server pages actually create servlets and rely on all of the information discussed so far. At the end of the book are a number of large examples, some of which use servlets to provide HTTP tunneling. Servlets are a flexible, powerful mechanism for creating server code and will probably fill a key role in your enterprise applications over the next few years.


Previous Table of Contents Next