Java Performance Design

Source: Internet
Author: User
Tags gety

 


Many programmers do not focus on performance design at the beginning. They can only discover and solve the problem when the system is delivered and run, but often this can only be saved a little. Performance management should be integrated into design and development at the beginning.

The most common problem is the frequent creation of a large number of temporary objects, which lays a hidden risk for performance.

Performance problems come from many reasons. The easiest solution is that you choose a bad Algorithm for Computing, such as sorting massive data using the bubble method, or you need to calculate the data again and again every time you use the data. This should use the Cache.

You can easily use tools (such as Borland's Optimizeit) or stress testing to find these problems, and once discovered, they can be corrected immediately, but many Java performance problems are hidden deeper, it is difficult to modify the source code, such as the interface design of program components.

Now we advocate object-oriented Component Reusable Design, which undoubtedly has a huge advantage, but we should also note the impact on performance.

A java performance design principle is to avoid unnecessary object creation and the object creation is very time-consuming. Therefore, you must avoid unnecessary temporary or excessive object creation,

String is the most important object to be created in the program. Because String is unchanged, if the length of String is modified, the String object will be created again. Therefore, the average person who pays attention to the performance should try to avoid using String, but this is almost impossible.

Interface Parameter Design

For example, MailBot:
The MailBot mail system has a Header data, which is a character buffer. You need to analyze and compare the character buffer. Then you need to make a Matcher class, in this class, you read the Header data and then compare it. A bad practice is:

Public class BadRegExpMatcher {
Public BadRegExpMatcher (String regExp );

/** Attempts to match the specified regular expression against the input text, returning the matched text if possible or null if not
*/
Public String match (String inputText );

}

This BadRegExpMatche requires that the entry parameter be String. If MailBot wants to call it, it must convert character buffer to String by itself:

BadRegExpMatcher dateMatcher = new BadRegExpMatcher (...);

While (...){...

// Generate a new String
String headerLine = new String (myBuffer, thisHeaderStart, thisHeaderEnd-thisHeaderStart );

String result = dateMatcher. match (headerLine );

If (result = null ){...}

}

Obviously, the creation of redundant String headerline object is not allowed due to inconsistent interfaces. The Matcher interface should be designed to accept character buffer, which is of course universal, the String interface parameters should also be provided:

Class BetterRegExpMatcher {
Public BetterRegExpMatcher (...);

/** Provide the match method for multiple interface parameters
Provide matchers for multiple formats of input -- String,
Character array, and subset of character array. Return
-1 if no match was made; return offset of match start if
A match was made .*/
 
Public int match (String inputText );
Public int match (char [] inputText );
Public int match (char [] inputText, int offset, int length );

/** Get the next match against the input text, if any */
Public int getNextMatch ();

Public int getMatchLength ();

Public String getMatchText ();
}

Obviously, BetterRegExpMatcher runs faster than BadRegExpMatcher.

Because it is difficult to change the interface parameters of a class when you have written the code, you should consider the type setting of these interface parameters before writing the program, it is better to have a comprehensive interface type specification.

Reduce object Creation

Temporary objects are those that have a short life cycle and usually serve some non-very useful goals. Programmers usually use temporary objects as data mixed packages for transmission or return, to avoid the construction of the conversion interface objects in the preceding example, you should avoid creating these temporary objects cleverly to prevent performance shadow to your program.

The above example shows that the performance problem lies in the String object, but the String is so common in object creation that the String is unchanged and will not change once the value is assigned, many Programmers think that constant things will always lead to bad performance. In fact, it is not so simple. In fact, the performance is how you use it.

For strings that often need to be changed, it is obvious that Stringbuffer is used instead.

Example:
See the following two implementations:

Public class Component {
...
Protected Rectangle myBounds;
Public Rectangle getBounds () {return myBounds ;}
}

And

Public class Component {
Public Rectangle getBounds (){
Return new Rectangle (myBounds. x, myBounds. y, myBounds. height,
MyBounds. width );
}
}

When Component is used, the following two methods should be used:

Rectangle r = component. getBounds ();

...

R. height * = 2;

And
Int x = component. getBounds (). x;
Int y = component. getBounds (). y;
Int h = component. getBounds (). height;
Int w = component. getBounds (). width;

Disadvantages of the first method: r. the use of height has been separated from component, which may lead to misunderstandings in communication, because Rectangle changes must involve re-refreshing of component content. In case other programmers do not know this rule, modify r. height (multiplied by 2) will not refresh component,

The second method is an improvement, which forces componenet to be followed by its components. However, the problem is that four temporary objects are created.

The improvement method is to add

Public int getX () {return myBounds. x ;}
Public int getY () {return myBounds. y ;}
Public int getHeight () {return myBounds. height ;}
Public int getWidth () {return myBounds. width ;}

In this way, the call becomes:
Int x = component. getX ();
Int y = component. getY ();
Int h = component. getHeight ();
Int w = component. getWidth ();

The best of both worlds, right?

This is one of the tips for reducing object creation: adding the finer-grained Auxiliary Function

The second technique is: Exploit mutability.

In the above example, there is another implementation method:

Public Rectangle getBounds (Rectangle returnVal ){
ReturnVal. x = myBounds. x;
ReturnVal. y = myBounds. y;
ReturnVal. height = myBounds. height;
ReturnVal. width = myBounds. width;
Return returnVal;

}

How clever is that the Rectangle is passed in as a parameter and modified before being sent out.

Tip 3 is integrated and unchanged.

To sum up the above examples, we found that temporary objects are generated in this case: the constant must be converted to a variable. For this root cause, we have designed different solutions.

The following is an example:

Point is unchanged. We inherit it and define a variable subclass.

Public class Point {
Protected int x, y;
Public Point (int x, int y) {this. x = x; this. y = y ;}
Public final int getX () {return x ;}
Public final int getY () {return y ;}
}

Public class MutablePoint extends Point {
Public final void setX (int x) {this. x = x ;}
Public final void setY (int y) {this. y = y ;}
}

In this way, the variable requirements and the immutable requirements are met and called separately.

Public class Shape {
Private MutablePoint myLocation;

// Return variable
Public Shape (int x, int y ){
MyLocation = new MutablePoint (x, y );
}

// Returns unchanged
Public Point getLocation () {return (Point) myLocation ;}}

Remote Interface

In distributed applications, performance is also very important. Here we will introduce how to simply predict the performance problems in distributed applications by checking the class interface.

In a distributed application, an object running in this system can call the method of another system object. This is achieved through many internal mechanisms that make remote objects look like local objects, to discover remote objects, you must first discover them through a naming directory service mechanism, such as RMO registration, JNDO, and CORBA name services.

When you get a remote object through the directory service, you don't get an actual point, but a point of a stub object with the same remote behavior, when you call a method of the stub object, the parameter marshal is obtained, that is, converted to byte-stream, which is similar to serialization, this stub object sends the parameters after marshal to the skeleton object through the network. The latter is responsible for the unmarshal parameters and then calls the real remote method you want to call. Then, this method returns a value to skeleton and returns one by one based on the previous route. A simple method is used to do so much work.

Obviously, remote method calls are more time-consuming than local method calls.

The above response indicates that the original type of primitive is returned. What should I do if the returned object is returned? If this object supports remote calls, it

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.