Java performance optimization skills highlights
Summary: ================================================================================================== Bandwidth, etc.) is limited, optimized to complete the predetermined task with as little resource as possible. Optimization usually contains two aspects: reduce the volume of the code, improve the operating efficiency of the code. This paper discussed how mainly how to improve the efficiency of code. =================================== Outline: ============= ======================1, universal articles 1. Unlike new keywords Creative classes Example 1.2 use non-blocking I / O 1.3 caution with exception 1.4 Do not repeat initialization Variable 1.5 Try to specify the Final modifier 1.6 to use local variables 1.7 multiplication and division II. J2EE 2.1 Use Buffer Terminal 2.2 Always pass the session bean Access Entity Bean 2.3 Select the appropriate reference mechanism 2.4 Setting read only attributes in the deployment descriptor 2.5 Bush Visits for EJB HOME 2.6 Implementing local interfaces for EJB 2.7 Generating primary key 2.8 timely clearing no longer need session 2.9 Close Using useless session 2.10 Servlet and memory use 2.12 HTTP Keep-Alive 2.12 JDBC and Unicode 2.13 JDBC I / O 1.14 Memory Database 3, GUI Article 3.1 Tips with JAR Compressed Class 3.2 Prompt Applet Load Process 3.3 Pre-put it before drawing graphs 3.4 override UPDATE Method 3.5 Delayed Heavy Pictures 3.7 Use BufferedImage 3.8 Using VolatileImage 3.9 using Window Blitting 4, supplementing data =================================== ========================================================================================================================================================================================================================= =================================1, general articles
The issue of "universal article" is suitable for most Java applications.
1.1 Examples of creating classes without NEW keywords
When you create an instance of a class with a new keyword, all constructors in the constructor chain are automatically called. But if an object implements a Cloneable interface, we can call its clone () method. The clone () method does not call any class constructor. In the case of design mode (Design Pattern), if you create an object with a Factory mode, you can use the Clone () method to create a new object instance is very simple. For example, the following is a typical implementation of the Factory mode:
Public static credit getnewcredit () {return new credit ();
?
The improved code uses the clone () method, as shown below:
Private static credit basecredit = new credit (); public static credit getnewcredit () {return (credit) Basecredit.clone ();
?
The above ideas is equally useful for array processing.
1.2 use non-blocking I / O
The low version of JDK does not support Non-block I / O APIs. In order to avoid I / O blocking, some applications use a way to create a large number of threads (in better case, using a buffer pool). This technology can be seen in many applications that must support concurrent I / O streams, 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 a version earlier JDK, there is a package that supports non-blocking I / O.
See the "Adjust Java I / O Performance" of the Sun China website.
1.3 cautious use
Exception is unfavorable. Throw an exception first to create a new object. The constructor of the Throwable interface calls the local (Native) method called FillInstackTrace (), and the FillInstackTrace () method checks the stack to collect the trace information. As long as there is an abnormality being thrown, the VM must adjust the calling stack because a new object is created during the processing.
An exception can only be used for error processing, and should not be used to control the program process.
1.4 Do not repeat initialization variables
By default, when the class constructor is called, Java initializes the variable into a determined value: all objects are set to NULL, integer variables (byte, short, int, long) set to 0, float and double variables set to 0.0, the logic value is set to false. This should especially note when a class is derived from another class, because all constructors in the constructor chain are automatically called when creating an object with the New keyword.
1.5 Try to specify the Final modifier class
Classes with Final modifiers are not born. In the Java core API, there are many examples of Final, such as java.lang.string. Specifying Final for String class to prevent people from overwriting the Length () method.
Also, if you specify a class for Final, all methods of this class are Final. The Java compiler looks for all the Final methods of inline (this and the specific compiler implementation). This move enables performance average by 50%.
1.6 Try to use local variables
The parameters passed when calling the method and the temporary variables created in the call are saved in the stack, and the speed is faster. Other variables such as static variables, example variables, etc. are created in the heap, slower speed. In addition, dependent on specific compiler / JVM, local variables may also be further optimized. See "Using Stack Variables as much as possible." 1.7 multiplication and division
Consider the following code:
FOR (VAL = 0; VAL <100000; VAL = 5) {alterx = val * 8; myresult = val * 2;}
?
The replacement of multiplication operation can greatly improve performance. Below 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 operation, but is used to switch to the equivalent left shift 3-bit operation, and one bit per left is equivalent to multiplying 2. Accordingly, the right shift 1 bit operation corresponds to division by 2. It is worth mentioning that although the shift is fast, it may make the code difficult to understand, so it is best to add some comments.
Second, J2EE articles
The improved performance techniques described above are suitable for most Java applications, and the problem to be discussed is suitable for applications of JSP, EJB or JDBC.
2.1 Use buffer marks
Some application servers have joined JSP buffer tags. For example, BEA's WebLogic Server starts supporting this feature from version 6.0, and the Open Symphony project also supports this feature. The JSP buffer tag can buffer the page segment and can buffer the entire page. When the JSP page is executed, if the target segment is already in the buffer, the code generated by generating the piece is not executed. Page-level buffer capture requests for the specified URL and buffer the entire result page. This feature is extremely useful for the homepage of the shopping basket, catalog, and portal. For such applications, the page-level buffer can save the result of the page execution, and the subsequent request is used.
For code logic complex pages, the effect of improving performance using buffer marks is more obvious; contrary, the effect may be slightly coupled.
See "Improve the performance and stability of JSP applications" with buffer technology.
2.2 Always access entity beans through session beans
Direct access entity beans are not conducive to performance. Each GET method is a remote call when the client remotely accesses entity beans. Session beans accessed to access entity beans are local, and all data can be organized into a structure and then returns its value.
Access to entity beans can improve transaction management because session beans will only be submitted when the transaction boundary is reached. Each direct call to the GET method generates a transaction, and the container will perform a "load-read" operation after each entity bean's transaction.
Time, using entity beans will lead to poor performance. If the unique use of entity beans is to extract and update data, it is changed to use the JDBC access database within session beans to get better performance.
2.3 Select the appropriate reference mechanism
In a typical JSP application, the header, the footer section is often extracted, then introduced to the page, footage as needed. Currently, there are two ways to introduce external resources in the JSP page. There are two: include instructions, and the include action.
Include instruction: for example <% @ include file = "Copyright.html"%>. This instruction introduces the specified resource when compiling. Before compiling, the pages with the include instructions and the specified resources are merged into one file. The referenced external resource is determined when compiling is more efficient than running. Include Action: For example,. This action introduces the result generated after the specified page execution. Since it is completed at runtime, the control of the output results is more flexible. However, when the referenced page cannot be determined when the referenced page is not determined when the referenced content is frequently changed, or when the request is not appeared on the main page, the use of the include action is used. 2.4 Setting read only properties in the deployment descriptor
The deployment of the entity bean allows all GET methods to be "read only". When a transaction unit is only included with a method of performing a read operation, setting the read-only property is conducive to improve performance because the container does not have to perform a storage operation.
2.5 Bush Visits for EJB HOME
The EJB HOME interface is obtained through the JNDI name. This operation requires considerable overhead. JNDI looks up in the init () method of servlet. If you frequent EJB access frequently, you will be best to create an EJBHomeCacche class. The EJBHomeCache class should generally be implemented as a Singleton.
2.6 Realizing the local interface for EJB
The local interface is the new content of EJB 2.0 specification, which allows Bean to avoid overhead of remote calls. 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 means that we have to look for the Home interface. This lookup is made through JNDI, it is an RMI call. Then, we locate the remote object, return to the proxy reference, which is also a RMI call. The second statement demonstrates how to create an instance, involving the Stub program that creates a IIOP request and transmits the request on the network, which is also a RMI call.
To achieve a local interface, we must make the following modifications:
The method can no longer throw a java.rmi.RemoteException, including exceptions derived from RemoteException, such as TransactionRequiredException, TransactionRolledBackexception, and NosuChobjectException. EJB provides equivalent local exception, such as TransactionRequiredLocalexception, TransactionRolledBackLocalexception, and NosuchobjectLocalexception. All data and return values are passed in a reference, not the transmission value. The local interface must be used on the machine deployed by the EJB. In short, the client and components of the service must run on the same JVM. If the bean implements a local interface, its reference is not serialized. See "Improve EJB Access Efficiency with local reference".
2.7 Generate the primary key
There are many ways to generate primary keys within EJBs, which analyzes several common methods and their characteristics.
Use the identification mechanism built in the database (SQL Server's Identity or Oracle's Sequence). The disadvantage of this method is that EJB portability is poor.
The primary key value (such as incremental operation) is calculated from the entity bean. Its disadvantage is that the transaction can be serialized and the speed is slow. Use clock services such as NTP. This requires a local code for a particular platform to secure the bean to a particular OS. In addition, it also leads to such a possibility that two primary keys are generated within the same millisecond on the multi-CPU server.
Borrow for Microsoft's ideas, create a GUID in the bean. However, if you do not help JNI, Java cannot determine the MAC address of the NIC; if you use JNI, the program is to depend on a specific OS.
There are several other ways, but these methods are the same limitations. It seems that only one answer is ideal: combined with RMI and JNDI. First bind the RMI remote object to the JNDI tree through the RMI registration. The client is looking for through JNDI. Below 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 Clear a session that is no longer required in time
In order to clear the no longer active session, many application servers have default session timeout, generally 30 minutes. When the application server needs to save more sessions, if the memory capacity is insufficient, the operating system shifts some memory data to disk, and the application server may also turn some unusual session according to the "most recent use" algorithm. Store to disk, may even throw "insufficient memory" exception. In a large-scale system, the cost of serialized sessions is very expensive. When the session is no longer needed, the httpsession.invalidate () method should be invoked to clear the session. HttpSession.INValidate () method can usually be called at the application's exit page.
2.9 Close the useless session in the JSP page
For those pages that do not have to track session status, shut down automatically created sessions can save some resources. Use the following Page instructions:
<% @ Page session = "false"%>
?
2.10 servlet and memory use
Many developers are free to save a lot of information into the user session. Time, the object stored in the session does not have a timely manner to be recycled by the garbage collection mechanism. From the performance, the typical symptom is that the user feels that the system is periodically slow, but it is not possible to attribute the reason to any particular component. If you monitor the heap space of the JVM, its performance is that the memory is not properly larger.
There are two main ways to solve such memory problems. The first method is to implement the HTTPSessionBindingListener interface in the BEAN of the session. Thus, as long as the valueUnbound () method is implemented, the resources used by the bean can be explicitly released.
Another way is to invalid the session as soon as possible. Most application servers have options for setting sessions as waste intervals. In addition, you can also call the session's setMaxinActiveInterVal () method in a program, which is used to set the maximum interval of the client requests allowed by the servlet container before the invalid session.
2.11 HTTP Keep-Alive
Keep-alive features continue to be valid for the client to the server-side connection, and the Keep-Alive function avoids establishing or re-establishing the connection when the server's subsequent request appears. Most web servers on the market, including IPlanet, IIS, and Apache, HTTP Keep-Alive supports. This feature is usually useful for sites that provide static content. However, there is another problem with the burden heavier website: although there is a certain advantage of reserved the open connection, it also affects performance, because during the handling of the suspension, the resources that can be released are still occupied. . When the web server and the application server run on the same machine, the KEEP-Alive function has a high impact of resource utilization. 2.12 JDBC and Unicode
Think of you have learned some measures to improve performance when using JDBC, such as using the connection pool, correctly select the stored procedure and direct SQL, from the result set delete the extra column, pre-compiling the SQL statement, and so on.
In addition to these obvious options, another good choice for improvement may be saved as Unicode (code page 13488). Java processes all data in Unicode, so the database driver does not have to perform a conversion process. But should be remembering: If this is used, the database will become larger because each Unicode character requires 2 byte storage space. In addition, if there are other non-Unicode program access to the database, performance issues still appear because the database driver still must perform a conversion process.
2.13 JDBC and I / O
If the application needs to access a large data set, you should consider using the block extraction method. By default, JDBC extracts 32 lines of data each time. For example, suppose we want to traverse a 5000 row of record sets, JDBC must call the database 157 times to extract all data. If the block size is changed to 512, the number of calls to the database will be reduced to 10 times.
This technology is invalid in some cases. For example, if you use the scrollable recording set, or specify for Update in the query, the block operation is no longer valid.
1.14 memory database
Many applications need to save considerable number of data in session objects in a session object, typical applications such as shopping baskets and directories. Since such data can be organized in the form of rows / columns, many applications have created huge vector or havehmap. Saving such data in a session greatly limits the scalability of the application because the memory has at least the memory of each session takes up with the maximum number of memory, which not only makes the server are expensive, but also garbage collection The time interval may also extend to an unbearable level.
Some people transfer the shopping basket / directory function to the database layer to a certain extent increase scalability. However, putting this part of the function in the database layer also has problems, and the root cause of the problem is related to the architecture of most relational database systems. For relational databases, one of the important principles of runtime is to ensure that all write operations are stable, reliable, and thus all performance issues are related to the ability to write data to disk physically. Relational database power map reduces I / O operation, especially for read operations, but the main way to achieve this goal is just a complex algorithm for implementing a buffer mechanism, which is the main Bottleneck of the database layer, usually the main CPU. the reason.
A solution for an alternative to traditional relational databases is to use a database that runs in memory (in-Memory Database), such as TIMESTEN. The starting point of the memory database is to allow data to be temporarily written, but these data do not have to be saved to disk permanently, all operations are in memory. In this way, the memory database does not require a complex algorithm to reduce I / O operation, and can adopt a relatively simple locking mechanism, so the speed is very fast. Third, GUI
The content introduced in this section is suitable for the application of graphical user interfaces (Applets and ordinary applications), to use AWT or SWING.
3.1 Use JAR compressed class files
The Java file (JAR file) is a compressed file according to JavaBean standard, which is the primary and recommended ways to publish JavaBean components. JAR file helps reduce file volume and shorten the download time. For example, it helps Applet increase the start speed. A JAR file can contain one or more related beans and support files such as graphics, sound, HTML, and other resources.
To specify a JAR file in an HTML / JSP file, just join the Archive = "name.jar" declaration in the Applet tag.
See "Using the file to improve the applet loading speed".
3.2 Tips Applet loading process
Have you seen the website that uses Applet, notice that a placeholder appears in a place where you should run Applet? What happens when the applet is downloaded? The biggest possibility is that the user will go out. In this case, the information displayed on an applet is undoubtedly helps to encourage users to wait.
Let's take a look at a specific implementation method. First create a small applet, the applet is responsible for downloading official 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 () {????? // Requires the official applet ????? LargeAppletName = getParameter ("applet"); ????? // "Please wait "Tip information ????? label = new label (" Please wait ... " largeappletname); ????? add (label); ??} ?? public void run () {????? ? Try {???????? // Get the class to be loaded with Applet ???????? Class LargeAppletClass = Class.Forname (LargeAppleTname); ???????? // Create to load Applet example ??????? Applet LargeApplet = (applet) LargeAppletClass.newinStance (); ????????? // Set the APPLET STUB program ??????? LargeApplet.setstub this); ???????? // Cancel "Please wait" information ??????? remove (label); ??????? // set layout ??????? SetLayout (New GridLayout (1, 0)); ??????? Add (LargeApplet); ??????? // Display formal applet ??????? LargeApplet.init ();? ?????? LargeApplet.Start (); ????} ???? catch (exception ex) {??????? // display error message ?????? label.setText "Don't load the specified applet"); ????} ???? // Refresh screen ???? validate () ;?}? Public void appletresize {??????? // Put AppleTResize from the Stub program Pass to Applet ?????? resize (width, height);?}}?
The compiled code is less than 2K, and the download speed is very fast. There are several places in the code worth noting. First, the preloader implements the AppletStub interface. Generally, Applet judges its own codeBase from the caller. In this case, we must call setstub () telling the applet where to extract this information. Another thing that is worth noting is that the AppletStub interface contains many ways with the Applet class, except for the AppleTResize () method. Here we pass the call to the AppleTResize () method to the Resize () method.
3.3 Push it before drawing the graph
ImageOBserver interface can be used to receive prompt information for graphics. The ImageOBserver interface has only one method imageUpdate (), which can draw graphics on the screen with a repaint () operation. An example is provided below.
Public Boolean ImageUpdate (Image IMG, INT FLAGS, INT X, INT Y, INT W, INT H) {???????? {(Flags & Allbits)! = 0 {???????? ????? repaint (); ????????} ???????? Else if (Flags & (Error | Abort))! = 0) {???????? ????? error = true; ?????????????? // file is not found, consider displaying a placeholder ????????????? repaint () ; ?????????} ????????? Return (Flags & (Allbits | Error | Abort) == 0;}?
When graphics information is available, the ImageUpdate () method is called. If further update is needed, the method returns true; if the required information has been obtained, the method returns false.
3.4 Cover UPDATE Method
The default action of the update () method is to clear the screen and then call the Paint () method. If you use the default Update () method, frequent use of graphics can display flicker. To avoid the screen clearance operation before Paint () call, you only need to override the update () method according to the following:
Public void update (graphics g) {??? paint (g);}
?
The more ideal solution is to override Update (), only the area that changes on the screen, as shown below:
Public void update (graphics g) {??? g.cliprect (x, y, w, h); ??? Paint (g);}
?
3.5 Delayed Heavy Picture Operation
For the application of the graphical user interface, the main reason why performance is often the efficiency of the heavy picture screen. This is usually obvious that the user changes the window size or scrolls one window. Changing the window size or the operation such as scrolling screen results in a large number of flash events to generate, and even exceeds the execution speed of the relevant code. The best way to deal with this problem is to ignore all "late" events.
It is recommended to introduce a few milliseconds here, that is, if we immediately receive another heavy draw event, stop processing the current event to handle the finals that the last received heavy draw event; otherwise, we continue to carry out the current heavy blow.
If the event is to start a time consuming, it is a good way to process a work thread; otherwise, some parts may be "freeze" because only one event can be handled each time. A simple example of an event handling is provided below, but it can be used to control the working thread after expansion.
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 the current time ????????? lastone.time = TIME; ????????? (New Thread () {public void Run () { ?????????????? IF (MilliseConds> 0) {?????????????????? Try {thread.sleep (MilliseConds); / Pause thread ??????????????????????????????????????????} ??????? ??????? synchronized (Lastone.Running) {// Waiting for the last event end ?????????????????? IF (Lastone.Time! = Time) // Only deal with the last event ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? }}). Start (); }?
3.6 Use a double buffer
A buffer drawing outside the screen, and immediately display the entire graph immediately after completion. Because there are two buffers, the program can switch back and forth. In this way, we can use a low priority thread to draw, so that the program can perform other tasks with idle CPU times. The pseudo code fragment below demonstrates this technology.
Graphics myGraphics; Image myOffscreenImage = createImage (size () width, size () height..); Graphics offscreenGraphics = myOffscreenImage.getGraphics (); offscreenGraphics.drawImage (img, 50, 50, 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 feature, Java must directly process pixels that make up text. Since this technique is to be done in memory, early JDK is in poor performance in using this technology. The Java standard proposed to solve this problem has achieved a new graphic type, which is bufferedimage.
The BufferedImage subclass describes the graphic with an accessible graphics data buffer. A bufferedImage contains a ColorModel and a set of raster graphics data. This class generally uses the RGB (red, green, blue) color model, but it can also handle grayscale graphics. Its constructor is simple, as shown below:
PUBLIC BUFFEREDIMAGE (int Width, Int height, int tentyste)?
ImageType allows us to specify what type of graphic to buffer, such as 5-bit RGB, 8-bit RGB, grayscale, etc.
3.8 Using VolatileImage
Many hardware platforms and their operating systems provide basic hardware acceleration support. For example, hardware acceleration typically provides rectangular filling, and hardware acceleration is more efficient than using CPUs to complete the same task. Since the hardware accelerates a part of the work, multiple workflows are allowed to perform concurrent, thereby alleviating the pressure on the CPU and the system bus, so that the application can run faster. Use VolatileImage to create hardware accelerated graphics and the content of management graphics. Since it directly uses the ability to use low-level platforms, the degree of improvement in performance depends primarily on the graphical adapter used by the system. The content of VolatileImage may be lost at any time, that is, it is "Volatile". Therefore, it is best to check if its content is lost before using the graph. VolatileImage has two ways to check if the content is lost:
Public Abstract Int Validate (GraphicsConfiguration GC); Public Abstract Boolean Contentslost ();
?
You should call the validate () method each time you copy content or write to VolatileImage, you should call the VOLATILATIMAGE object. The contentslost () method tells us that since the last Validate () call, the content of the graph is lost.
Although VolatileImage is an abstract class, don't send a child class from it. VolatileImage should be created by Component.createVolatileImage () or GraphicsConfiguration.createCompaVolatileImage () method.
3.9 Using Window Blitting
When scrolling operation, all visible content generally want to scroll, resulting in a lot of unnecessary heavy paintings. Many operating systems of graphic subsystems, including Win32 GDI, MacOS, and X / Windows, support Window Blitting Technology. Window Blitting technology moves the graphics directly to a new location in the screen buffer, only the new area. To use Window Blitting technology in Swing applications, the setting method is as follows:
SetscrollMode (int mode);
?
In most applications, this technique can be used to improve scrolling speed. Only in one case, Window Blitting will result in a reduction in performance, that is, the application is scrolling in the background. If the user is scrolling an application, it is always at the front desk, there is no need to worry about any negative impact.
Fourth, supplementary information
CCW: Java Performance Optimization (Part) China: Java Tips 86: Local Drawing in JDK1.3 Support IBM DeveloperWorks China: Java Tips 90: Accelerate GUI's SpeedWorks China: Write Efficient Thread Safety Class IBM DeveloperWorks China: Connection Pool: Deep J2EE connection