Experience Summary: Java Performance Optimization Skills collection

Source: Internet
Author: User
Tags error handling execution final garbage collection sql variables static class stub
Skills | experience | performance | optimization One, general article

The issues discussed in "common article" are appropriate for most Java applications.

  1.1 Create an instance of a class without the New keyword

When you create an instance of a class with the new keyword, all constructors in the chain of the constructor are invoked automatically. But if an object implements the Cloneable interface, we can call its clone () method. The Clone () method does not call any class constructors.

In situations where design patterns are used, if you create objects in Factory mode, it is simple to use the Clone () method instead to create a new object instance. For example, the following is a typical implementation of the factory pattern:

public static Credit Getnewcredit () {
Return to new credit ();
}

The improved code uses the Clone () method, as follows:

private static Credit Basecredit = new Credit ();
public static Credit Getnewcredit () {
return (Credit) Basecredit.clone ();
}

The above ideas are also useful for array processing.

  1.2 using non-blocking I/O

The less-than-version JDK does not support non-blocking I/O APIs. To avoid I/O blocking, some applications use a method of creating a large number of threads (in better cases, a buffer pool is used). This technique can be seen in a number of applications that must support concurrent I/O flows, such as Web servers, quotes, and auction applications. However, creating a Java thread requires considerable overhead.

JDK 1.4 introduces a non-blocking I/O library (Java.nio). If the application requires the use of an older JDK, there is a package that supports non-blocking I/O.

See the Sun China website, "Tuning Java I/O performance".

  1.3 Cautious use of abnormal

Exceptions are bad for performance. Throwing an exception begins by creating a new object. The constructor of the Throwable interface calls the local (Native) method named Fillinstacktrace (), and the Fillinstacktrace () method checks the stack to collect call tracking information. Whenever an exception is thrown, the VM must adjust the call stack because a new object is created during the process.

Exceptions can only be used for error handling and should not be used to control the process.

  1.4 Do not repeat initialization of variables

By default, when the constructor of a class is invoked, Java initializes the variable to the determined value: All objects are set to NULL, the integer variable (byte, short, int, long) is set to 0,float and the double variable is set to 0.0, and the logical value is set to False. This should be especially noted when a class derives from another class, because when an object is created with the new keyword, all constructors in the chain of the constructor are invoked automatically.

  1.5 Specify the final modifier for the class as much as possible

A class with the final modifier is not derived. In the Java Core API, there are many examples of final application, such as java.lang.String. Specifying final for the string class prevents people from overwriting the length () method.

In addition, if you specify that a class is final, all methods of that class are final. The Java compiler looks for the opportunity to inline (inline) all final methods (this is related to the specific compiler implementation). This will increase performance by an average of 50%.

  1.6 Use local variables as much as possible

The parameters passed when the method is invoked and the temporary variables created in the call are saved in the stack (stack) faster. Other variables, such as static variables, instance variables, and so on, are created in the heap (Heap) in a slower speed. In addition, local variables may be further optimized depending on the specific compiler/JVM. See Using stack variables whenever possible.

  1.7 Multiplication and Division

Consider the following code:

for (val = 0; Val < 100000 Val +=5) {Alterx = val * 8; myresult = val * 2;}

Using shift operations to replace multiplication operations can greatly improve performance. Here is the modified code:

for (val = 0; Val < 100000; Val + 5) {Alterx = Val << 3; myresult = Val << 1;}

The modified code is no longer multiplied by 8, instead using an equivalent left 3-bit operation, with 1 bits per left being multiplied by 2. Accordingly, the right 1-bit operation is the equivalent of dividing by 2. It is worth mentioning that, although the shift operation is fast, but may make the code more difficult to understand, so it is best to add some comments.

  

Second, the Java-ee article

The improved performance techniques described earlier are suitable for most Java applications, and the next issues to be discussed are suitable for use with JSP, EJB, or JDBC applications.

  2.1 using the buffer tag

Some application servers have added a JSP-oriented buffer tag function. For example, BEA's WebLogic server supports this feature from version 6.0, and the Open Symphony Project also supports this feature. The JSP buffer tag can either buffer the page fragment or buffer the entire page. When the JSP page executes, if the target fragment is already buffered, the code that generates the fragment does not have to be executed. The page-level buffer captures the request for the specified URL and buffers the entire results page. This feature is extremely useful for shopping baskets, directories, and the home page of the portal site. For such applications, page-level buffering can save the results of the page execution for subsequent requests.

For pages with complex code logic, the effect of using buffer tag to raise performance is obvious; Conversely, the effect may be slightly inferior.

See improving performance and stability of JSP applications with buffering techniques.

  2.2 always access entity beans through session bean

Direct access to entity beans is not conducive to performance. When a client program accesses an entity bean remotely, each get method is a remote call. The session bean that accesses the entity bean is local, can organize all the data into a structure, and then returns its value.

Encapsulating access to entity beans with session beans can improve transaction management because session beans are not committed until the transaction boundary is reached. Each direct call to a GET method produces a transaction that performs a mount-read operation after the transaction of each entity bean.

Sometimes, using entity beans can result in poor program performance. If the only purpose of an entity bean is to extract and update data, it can be better performance to use JDBC to access the database within the session bean.

  2.3 Select the appropriate referral mechanism

In a typical JSP application system, the header, footer parts are often extracted, and then introduced to the page header, footer. Currently, there are two main ways to introduce external resources into JSP pages: include directives, and include actions.

Include directives: For example, <%@ include file= "copyright.html"%>. The directive introduces the specified resource at compile time. Before compiling, a page with an include directive and a specified resource are merged into a single file. The referenced external resource is determined at compile time, and it is more efficient to determine the resource than the runtime.
Include actions: For example, <jsp:include page= "copyright.jsp"/>. This action introduces the results generated after the specified page is executed. Because it is completed at run time, the control of output results is more flexible. However, it is only cost-effective to use the include action when the referenced content changes frequently, or the referenced page cannot be determined until the request for the main page is not present.

  2.4 Setting read-only properties in the deployment descriptor

The deployment descriptor for the entity Bean allows all get methods to be set to read-only. Setting a read-only property is advantageous for performance when a transaction unit's work contains only methods that perform read operations, because the container does not have to perform storage operations again.

  2.5 buffering access to EJB home

The EJB home interface is obtained by Jndi name lookup. This operation requires considerable overhead. The Jndi lookup is best placed inside the servlet's init () method. If EJB access is frequent in multiple applications, it is best to create a Ejbhomecache class. Ejbhomecache classes should generally be implemented as singleton.

  2.6 Implementing the Local interface for EJB

The local interface is new to the EJB 2.0 specification, which enables the bean to avoid the overhead of remote invocation. Please consider the following code.

Paybeanhome home = (paybeanhome)
Javax.rmi.PortableRemoteObject.narrow
(Ctx.lookup ("Paybeanhome"), Paybeanhome.class);
Paybean bean = (paybean)
Javax.rmi.PortableRemoteObject.narrow
(Home.create (), paybean.class);

The first statement indicates that we are looking for the bean's home interface. This lookup is done through Jndi, which is an RMI call. We then locate the remote object and return the proxy reference, which is also an RMI call. The second statement demonstrates how to create an instance involving a stub program that creates a IIOP request and transmits the request over the network, which is also an RMI call.

To implement the local interface, we must make the following modifications:

Method can no longer throw java.rmi.RemoteException exceptions, including exceptions derived from remoteexception, such as Transactionrequiredexception, Transactionrolledbackexception and Nosuchobjectexception. EJBs provide an equivalent local exception, such as Transactionrequiredlocalexception, Transactionrolledbacklocalexception and Nosuchobjectlocalexception.

All data and return values are passed by reference, rather than by passing values.
The local interface must be used on the machine where the EJB is deployed. In short, client programs and serviced components must be running on the same JVM.
If the bean implements the local interface, its reference is not serializable.
See increasing EJB access efficiency with local references.

  2.7 Generating primary keys

There are many ways to generate primary keys within EJBS, and the following analysis of several common approaches and their characteristics.

Leverages the identity mechanism built into the database (identity of SQL Server or Oracle sequence). The disadvantage of this approach is the poor EJB portability.

The entity bean computes its own primary key value (for example, doing an incremental operation). Its disadvantage is that transactions are required to be serializable and are slower.

Use clock services such as NTP. This requires local code for a specific platform to secure the bean onto a specific OS. In addition, it leads to the possibility that two primary keys are generated in the same millisecond on a multiple-CPU server.

Use Microsoft's ideas to create a GUID in the bean. However, if you do not resort to Jni,java, you cannot determine the MAC address of the NIC, and if you use JNI, the program depends on the specific OS.

There are several other options, but they also have their own limitations. There seems to be an ideal answer: combine RMI and Jndi. The RMI remote object is bound to the Jndi tree first through RMI registration. The client is looking through Jndi. Here is an example:

public class Keygenerator extends UnicastRemoteObject implements Remote {
private static Long keyvalue = System.currenttimemillis ();
public static synchronized Long Getkey () throws remoteexception {return keyvalue++;}

  2.8 Timely removal of sessions no longer needed

To purge sessions that are no longer active, many application servers have a default session timeout, typically 30 minutes. When the application server needs to save more sessions, if the memory capacity is insufficient, the operating system will transfer part of the memory data to disk, and the application server may dump some inactive sessions to disk according to the "Most Frequently used" (Most recently Used) algorithm, and may even throw out "out-of-memory" Abnormal. In a large scale system, the cost of a serialized session is expensive. When the session is no longer needed, the Httpsession.invalidate () method should be called in time to clear the session. The Httpsession.invalidate () method can usually be invoked on the application's exit page.

  2.9 Turning off unwanted sessions in a JSP page

For pages that do not need to track session state, turning off an automatically created session can save some resources. Use the following page directive:

<%@ page session= "false"%>

  2.10 servlet and memory usage

Many developers randomly store large amounts of information in user sessions. At some point, objects saved in the session are not recycled by the garbage collection mechanism in a timely manner. In terms of performance, the typical symptom is that the user feels the system slows down periodically, but cannot attribute the reason to any particular component. If you monitor the JVM's heap space, it behaves as if the memory footprint is abnormally fluctuating.

There are two main ways to solve this type of memory problem. The first approach is to implement the Httpsessionbindinglistener interface in all the beans that are scoped to the session. In this way, the resources used by the bean can be explicitly freed as long as the Valueunbound () method is implemented.

Another way is to void the conversation as quickly as possible. Most application servers have an option to set session invalidation intervals. Alternatively, you can programmatically invoke the Setmaxinactiveinterval () method of the session, which is used to set the maximum interval, in seconds, that the servlet container allows for client requests before a voided session.

  2.11 HTTP keep-alive

The Keep-alive feature enables client-side connections to the server to remain valid, and when a subsequent request is made to the server, the Keep-alive function avoids establishing or reconnecting the connection. Most Web servers on the market, including Iplanet, IIS, and Apache, support HTTP keep-alive. This feature is often useful for Web sites that provide static content. However, there is another problem with heavier Web sites: While retaining open connections for customers has some benefits, it also affects performance because the resources that could have been freed during the process of a pause are still occupied. When the Web server and application server are running on the same machine, the impact of keep-alive function on resource utilization is particularly prominent.

  2.12 JDBC and Unicode

Presumably you already know some of the things that improve performance when using JDBC, such as using connection pooling, correctly selecting stored procedures and directly executing SQL, removing redundant columns from the result set, precompiling SQL statements, and so on.

In addition to these obvious choices, another good choice for performance might be to save all character data as Unicode (code page 13488). Java processes all data in Unicode, so the database driver does not have to perform the conversion process again. It should be remembered, however, that in this way the database becomes larger because each Unicode character requires 2 bytes of storage space. Also, if there are other non-Unicode programs accessing the database, performance problems still occur because the database driver still has to perform the conversion process.

  2.13 jdbc and I/O

If your application needs access to a large dataset, you should consider using block extraction. By default, JDBC extracts 32 rows of data at a time. For example, if we were to traverse a 5000-row recordset, JDBC must call the database 157 times to extract all the data. If you change the block size to 512, the number of calls to the database is reduced to 10 times.

In some cases this technique is ineffective. For example, if you use a scrollable recordset, or if you specify a for UPDATE in the query, the block action is no longer valid.

  2.14 Memory Database

Many applications need to hold a significant amount of data in the session object in the user unit, typical applications such as shopping baskets and catalogs. Since such data can be organized in the form of rows/columns, many applications create large vectors or hashmap. Saving this type of data in a session greatly limits the scalability of the application because the server has at least the amount of memory that is consumed by each session multiplied by the maximum number of concurrent users, which not only makes the server expensive, but also can extend the time interval of garbage collection to intolerable levels.

Some people move the shopping basket/directory function to the database layer, which increases scalability to some extent. However, it is also problematic to put this part of the function into the database layer, and the source of the problem is related to the architecture of most relational database systems. For relational databases, one of the important principles of the runtime is to ensure that all writes are stable and reliable, so that all performance problems are related to the ability to physically write data to disk. Relational databases attempt to reduce I/O operations, especially for read operations, but the main way to achieve this goal is to implement a set of complex algorithms that implement buffering mechanisms, which is the main reason why the first performance bottleneck in the database tier is always CPU.

An alternative to traditional relational databases is to use databases that run in memory (In-memory database), such as TimesTen. The starting point of the memory database is to allow the data to be written temporarily, but the data does not have to be permanently saved to disk, and all operations are performed in memory. In this way, the memory database does not require complex algorithms to reduce I/O operations, and can adopt a relatively simple locking mechanism, so fast.

  

Third, GUI article

This section covers the application of the graphical user interface (applets and general applications) to use AWT or swing.

  3.1 compressing class files with jars

The Java archive (JAR file) is the main way and recommendation for  ⒉ 糐 Avabean components based on JavaBean Ku Yunai. Jar files help reduce file volume and shorten download time. For example, it helps applets improve startup speed. A jar file can contain one or more related beans and supporting files, such as graphics, sounds, HTML, and other resources.

To specify a jar file in the html/jsp file, simply add the archive = "Name.jar" declaration to the applet tag.

See "Using profiles to increase the loading speed of applets".

  3.2 Prompts the applet to mount the process

Have you ever seen a Web site that uses applets, and noticed that a placeholder appears where you should run the applet? What happens when the applet downloads for a long time? The biggest possibility is that users will turn around and leave. In this case, displaying the information an applet is downloading undoubtedly helps to encourage the user to continue waiting.

Now let's take a look at a specific implementation method. Start by creating a small applet that is responsible for downloading the formal applets in the background:

Import Java.applet.Applet;
Import java.applet.AppletStub;
Import Java.awt.Label;
Import Java.awt.Graphics;
Import Java.awt.GridLayout;
public class Preloader extends Applet implements Runnable, Appletstub {
String Largeappletname;
Label label;
public void init () {
Formal applets required for loading
Largeappletname = GetParameter ("applet");
"Please wait" message
Label = new label ("Please wait ..." + largeappletname);
Add (label);
}
public void Run () {
try {
Get classes to load applets
Class Largeappletclass = Class.forName (largeappletname);
Create an instance of an applet to be loaded
Applet Largeapplet = (applet) largeappletclass.newinstance ();
Set stub program for this applet
Largeapplet.setstub (this);
Cancel the "Please wait" message
Remove (label);
Set layout
SetLayout (New GridLayout (1, 0));
Add (Largeapplet);
Show the Formal applet
Largeapplet.init ();
Largeapplet.start ();
}
catch (Exception ex) {
Display error messages
Label.settext ("Cannot load the specified applet");
}
Refresh Screen
Validate ();
}
public void appletresize (int width, int height) {
Pass the Appletresize call from the stub program to the Applet
Resize (width, height);
}
}

The compiled code is less than 2K and the download speed is fast. There are several places in the code that deserve attention. First, the Preloader implements the Appletstub interface. In general, applets judge their own codebase from the caller. In this case, we have to call Setstub () to tell the applet where to extract this information. Another noteworthy point is that the Appletstub interface contains many of the same methods as the Applet class, except for the Appletresize () method. Here we pass the call to the Appletresize () method to the Resize () method.

  3.3 Pre-loading the graphic before drawing it

The ImageObserver interface can be used to receive hints about graphics loading. The ImageObserver interface has only one method Imageupdate (), capable of drawing graphics on the screen with a repaint () operation at a time. An example is provided below.

public boolean imageupdate (Image img, int flags, int x, int y, int w, int h) {
if (Flags & allbits)!=0 {
Repaint ();
}
else if (Flags & ERROR | ABORT))!= 0) {
Error = TRUE;
File not found, consider displaying a placeholder
Repaint ();
}
Return (Flags & Allbits | error| ABORT) = = 0;
}

The Imageupdate () method is invoked when the graphic information is available. This method returns true if further updates are required, and false if the required information has been obtained.

  3.4 Overwrite Update method

The default action for the update () method is to clear the screen and then invoke the paint () method. If you use the default update () method, applications that use graphics frequently may display flicker. To avoid screen cleanup before the paint () call, simply overwrite the update () method as follows:

public void Update (Graphics g) {
Paint (g);
}

A more desirable scenario would be to overwrite update () and only redraw the changed area of the screen as follows:

public void Update (Graphics g) {
G.cliprect (x, Y, W, h);
Paint (g);
}

  3.5 Deferred repaint Operation

For the application of graphical user interface, the main reason of low performance often boils down to the inefficiency of painting screen. This can often be observed when the user changes the window size or scrolls through a window. Actions such as changing the window size or scrolling the screen cause the redraw screen events to generate massively, quickly, or even exceed the execution speed of the associated code. The best way to deal with this problem is to ignore all "late" events.

It is recommended to introduce a millisecond time difference here, that is, if we receive another redraw event immediately, we can stop processing the current event instead of the last one received, otherwise we continue with the current redraw process.

If an event is to start a time-consuming task, separating a worker thread is a good way to do it; otherwise, some parts may be "Frozen" because only one event can be processed at a time. A simple example of event handling is provided below, but it can be used to control worker threads after it has been extended.

public static void RunOnce (String ID, final long milliseconds) {
Synchronized (e_queue) {//E_queue: Collection of all events
if (!e_queue.containskey (ID)) {
E_queue.put (token, new LaStone ());
}
}
Final LaStone LaStone = (lastone) e_queue.get (token);
Final long time = System.currenttimemillis (); Get current time
Lastone.time = time;
(New Thread () {public void run () {
if (milliseconds > 0) {
try {thread.sleep (milliseconds);}//Pause thread
catch (Exception ex) {}
}
Synchronized (lastone.running) {//Waiting for the last event to end
if (lastone.time!= time)//Only the last event is processed
Return
}
}). Start ();
}
private static Hashtable E_queue = new Hashtable ();
private Static Class LaStone {
public long time=0;
Public Object running = new Object ();
}

  3.6 using double buffers

Draw the buffer outside the screen and display the entire graphic as soon as it is finished. Because there are two buffers, the program can switch back and forth. In this way, we can use a low priority thread to paint, allowing the program to take advantage of idle CPU time to perform other tasks. The following pseudocode snippet demonstrates this technique.

Graphics Mygraphics;
Image myoffscreenimage = createimage (Size (). width, size (). height);
Graphics offscreengraphics = Myoffscreenimage.getgraphics ();
Offscreengraphics.drawimage (IMG, M, this);
Mygraphics.drawimage (myoffscreenimage, 0, 0, this);

  3.7 using BufferedImage

Java JDK 1.2 uses a soft display device that makes text look similar on different platforms. To implement this functionality, Java must directly handle the pixels that make up text. Because of the large amount of bit-copying operations in memory, the early JDK had poor performance in using the technology. The Java standard proposed to solve this problem implements a new type of graphics, namely BufferedImage.

The graph described by the BufferedImage subclass has an accessible graphics data buffer. A bufferedimage contains a ColorModel and a set of raster graphics data. This class generally uses an RGB (red, green, blue) color model, but it can also handle grayscale graphics. Its constructor is simple, as follows:
public bufferedimage (int width, int height, int imagetype)

ImageType allows us to specify what type of graphics to buffer, such as 5-bit RGB, 8-bit RGB, gray level, and so on.

  3.8 using Volatileimage

Many hardware platforms and their operating systems provide basic hardware acceleration support. For example, hardware acceleration generally provides rectangular padding, and hardware acceleration is more efficient than using the CPU to accomplish the same task. Since hardware acceleration separates a part of the work, allowing multiple workflows to be performed concurrently, relieving the pressure on the CPU and system bus so that applications can run faster. With Volatileimage, you can create graphics for hardware acceleration and manage the content of graphics. Because it directly utilizes the capabilities of the lower platform, the performance improvement depends largely on the graphics adapter used by the system. The content of the volatileimage may be lost at any time, i.e. it is "unstable" (volatile). So before you use graphics, it's a good idea to check that the content is missing. Volatileimage has two ways to check whether the content is missing:

public abstract int Validate (graphicsconfiguration GC);
Public abstract Boolean contentslost ();

Each time you copy content from a Volatileimage object or write to Volatileimage, you should call the Validate () method. The Contentslost () method tells us whether the contents of the graphic have been lost since the last validate () call.

Although Volatileimage is an abstract class, do not derive subclasses from it. Volatileimage should be created through the component.createvolatileimage () or Graphicsconfiguration.createcompatiblevolatileimage () method.

  3.9 Using Window blitting

When scrolling, all the visible content is typically repaint, resulting in a large amount of unnecessary repaint work. The graphics subsystems of many operating systems, including WIN32 GDI, MacOS, and x/windows, Support window blitting technology. The Window blitting technology moves the graphic to a new location directly in the screen buffer, only to redraw the newly-appearing area. To use window blitting technology in swing applications, set the method as follows:

Setscrollmode (int mode);

In most applications, the use of this technique can improve scrolling speed. Only in one case, Window blitting can cause performance degradation, that is, the application is scrolling in the background. If the user is rolling an application, then it is always in the foreground, without worrying about any negative effects.



Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.