Practices to improve Performance in JSP
February 21, 2008 by muralis
Overview of JSP
When the user requests a JSP page for the first time, A JSP converts into servlet java source file and compiles into servlet class file that is called as translation phase, then onwards it works like pure servlet for all requests this is called execution/request process phase. But the method signatures are different for both Servlet and JSP. Servlet has init(), service() and destroy() methods where as JSP has jspInit(), _jspService() and jspDestroy() methods. JSP has some advantages over servlet. JSP gives good separation between presentation (html) and business logic.
Use jspInit() method as cache
The default mechanism of a JSP Engine is to load a JSP’s servlet in multithreaded environment, that is the default value of page directive in JSP’s
In this environment, a JSP’s jspInit() method is called only once in its life time. Here is a trick that you can use to improve performance using jspInit() method. You can use this method to cache static data.
Generally a JSP generates not only dynamic data but also static data. Programmers often make a mistake by creating both dynamic and static data from JSP page. Obviously there is a reason to create dynamic data because of its nature but there is no need to create static data every time for every request in JSP page.
For example, normally you would write a JSP page like this
//creating static data and pass it to client
out.print(””);
out.print(””);
out.print(“”);
// create the dynamic data and pass it to client here
//creating static data again and passing it to client
out.print(“”);
out.print(””);
Here you are generating both static data and dynamic data from _jspService() method. Instead what you can do is
char[] header;
char[] navbar;
char[] footer;
char[] otherStaticData;
public void jspInit(){
//create all the static data here
StringBuffer sb = new StringBuffer(); // better to initialize the StringBuffer with some size to improve performance
sb.append(””);
sb.append(””);
sb.append(“”);
header = sb.toString().toCharArray();
// do same for navbar if its data is static
// do same for footer if its data is static
} // end jspInit() method
out.print(header);
out.print(navbar);
// write dynamic data here
out.print(footer);
}
Here the static data is created in jspInit() method which means that it is created only once in the life time of JSP and it is used in _jspService() method to pass the data to the client. When you send a large amount of static data, then you can use this technique to see a considerable increase in performance.
Optimization techniques in _jspService() method
When you use implicit out object to pass the data to the client from JSP, the JSP Engine/container creates a JSPWriter object and put it in the _jspService() method. You don’t need to bother about writing _jspService() method in your JSP, JSP Engine does that work for you. You can improve performance by using the following techniques.
1. Use StringBuffer rather than using + operator when you concatenate multiple strings
2. Use print() method instead of println() method of out (implicit) object
3. Use ServletOutputStream instead of JSPWriter
4. Initialize out with proper size in the page directive
5. Flush the data partly
6. Minimize the amount of code in the synchronized block
7. Set the content length
1. Use StringBuffer for concatenation rather than using + operator. See Concatenating Strings for detailed information.
2. println() method internally calls print() method and there is no need for a new line separation when generating html pages. So a small overhead of calling one more method is reduced if you use print() method directly.
3. There is a small overhead involved in JSPWriter because it is meant for character output stream and it encodes data to bytes, rather you can directly use ServletOutputStream whenever you want to send binary data.
4. Initialize the out object with proper size in the page directive. It is discussed in detail in later part of this section.
5. If you want to pass huge data to the client from your servlet, user may need to wait till the ServletOutputStream or JSPWriter flushes the data. This happens generally whenever you have a number of gifs per page and you want to pass it to the client. The better approach is to flush the data partly using flush() method rather than flushing whole data at a time. You can initially flush header, then navigation bar, then body content and finally footer so that the user need not wait for whole data and he sees the header data immediately and so on with navigation bar, body content and footer.
out.write(header);
out.flush(); // flush the header
out.write(navbar);
out.flush(); // flush the navigation bar
// write dynamic data here
out.flush(); // flush the dynamic data
out.write(footer);
out.flush(); // finally flush the footer
6. Minimize the amount of code in the synchronized block that is used in the service method whenever you want the data to be thread safe.
for example, you may write like this
synchronized(this){
code line1;
code line2;
code line3;
code line4;
}
but here if you want only to synchronize the data in the code line2 instead of all the lines,the better way is
code line1;
synchronized(this){code line2;}
code line3;
code line4;
This reduces the overhead of locking all the code lines.
7. Whenever the client, such as a browser requests a page it establishes socket connection internally with the web server to get the requested content. Client gets the page data with multiple connections depending on size of the data. If the data is more, such as with multiple gifs then it needs to establish connection for multiple times to get the data. The number of connections established will depend on default content length of the header, and size of the content to be traversed from web server to the client. By increasing content length, you can reduce traffic and increase the performance. Here is a sample of what you can do
response.setContentLength(int contentSize);
This method sets the length of the content so that the server can send data to the client by using Content-Length header.
Optimization techniques in jspDestroy() method
The jspDestroy() method is called only once in JSP’s servlet life time, when the JSP Engine removes the JSP’s servlet from memory. It is always better to remove instance variable resources such as JDBC connections, sockets, other physical resources in this method to avoid memory leaks.
Optimization techniques in page directive
Page directive defines attributes that apply to an entire JSP page. Here is an example of page directive.
bold values are default values. Here I have shown only a few attributes, these attributes have an impact on the performance so we will discuss about them here.
By default JSP Engine creates session object. If you don’t want to use built in HttpSession for a JSP, then make session attribute value as false. It avoids unnecessary creation of session (implicit) object, reduces overhead on memory and garbage collector and increases performance.
By default the size of out (implicit object of JSPWriter) object is 8kb. You can increase the size if you are sending a large amount of data.
so set
Here you need to set the size as per page response data if it crosses 8kb.
Choosing the right include mechanism
There are two include mechanisms available to insert a file in a JSP page. They are
1. include directive
2. include action
The include directive includes the content of the file during the translation phase where as include action includes the content of the file during execution/request processing phase.
For include directive, JSP Engine adds the content of the inserted page at translation phase, so it does not have an impact on performance.
For include action, JSP Engine adds the content of the inserted page at run time which imposes extra overhead.
Key Points
1. Use jspInit() method to cache static data
2. Use StringBuffer rather than using + operator when you concatenate multiple strings
3. Use print() method rather than println() method
4. Use ServletOutputStream instead of JSPWriter to send binary data
5. Initialize the ‘out’ object (implicit object) with proper size in the page directive.
6. Flush the data partly
7. Minimize code in the synchronized block
8. Set the content length
9. Release resources in jspDestroy() method.
10. Give ‘false’ value to the session in the page directive to avoid session object creation.
11. Use include directive instead of include action when you want to include the child page content in the translation phase.
12. Avoid giving unnecessary scope in the ‘useBean’ action.
13. Do not use custom tags if you do not have reusability.
14. Use application server caching facility
15. Use Mixed session mechanisms such as ’session’ with hidden fields
16. Use ’session’ and ‘application’ as cache.
17. Use caching tags provided by different organizations like openSymphony.com
18. Remove ’session’ objects explicitly in your program whenever you finish the task
19. Reduce session time out value as much as possible
20. Use ‘transient’ variables to reduce serialization overhead if your session tracking mechanism uses serialization process.
21. Disable JSP auto reloading feature.
22. Use thread pool for your JSP engine and define the size of thread pool as per application requirement.
This is Good. And very usefull….
Thanx