JVM Optimization Technology

Source: Internet
Author: User
Tags scalar

1. One of the classical optimization techniques not related to language: Common sub-expression elimination

Common subexpression Elimination is a classic optimization technique that is commonly applied to various compilers, meaning that if an expression e has been computed and the value of all the variables in E has not changed since the previous calculation, then the appearance of e has become a common subexpression, and for such an expression, There is no need to take the time to calculate it, just use the previously computed expression results instead of E,

Give an example of the optimization process, assuming the following code

int d = (c*b) *12 + A + (A+B*C)

If this code is given to the Javac compiler, no optimizations are made, and the resulting code is as follows:


When this code goes into the virtual machine instant compiler, it optimizes the following: The compiler detects that "C*b" is the same expression as "b*c", and that the value of B and C is constant during the calculation, so this expression is considered:

int d = E *12 + A + (a+e)

At this point the compiler may also (depending on which virtual machine compiler and the specific context) perform another optimization: algebraic simplification, which changes the expression to:

int d = E *13 + A * *;

2. One of the classic optimization techniques that is not language-agnostic: array range Check elimination

Array boundary Check elimination is a language-related classic optimization technique in the immediate compiler. Java is a dynamic security of the language, read and write access to the array is not like C, C + + is essentially a bare pointer operation, if there is an array foo[], in the Java language access to the array element Foo[i], the system will automatically perform the upper and lower bounds of the bounds of the check, that is, check I must meet the i>=0 &&i<=foo.length this condition, otherwise a run-time exception will be thrown: Java

. lang. ArrayIndexOutOfBoundsException.

For security, array bounds checking must be necessary, but the array bounds check is not a must during the run time does not leak the check is can "negotiate" things, for example: array subscript is a constant, foo[3], as long as the compilation period according to data flow analysis to determine the value of foo.length, and judge subscript "3 "There is no cross-border, there is no need to judge the execution time, the more common case is that the array access occurs in the loop, and the use of the loop variable to access the array, if the compiler as long as the data stream analysis can determine the value of the loop variable is always within the range [0.foo.length], That can eliminate the upper and lower bounds of the array throughout the loop, which can save many times of conditional judgment.

3. One of the most important optimization techniques: Method Inline

Method Inline, is one of the most important optimization methods of compiler, besides eliminating the cost of method invocation, it is more important to establish good foundation for other optimization methods.

Foo (Object obj) {    ifnull) {        System.  out. println ("do sometthing"); }}testinline(string[] args) {null;          Foo (obj);}      

In fact, the interior of the Testinline () method is all useless code, and if you do not inline, subsequent optimizations that do not eliminate the unwanted code will not be able to find any "Dead code" because, if viewed separately, foo () and Testinline () The actions within the two methods can be meaningful.

The inline optimization behavior of the method looks simple, but the code of the target method is "copied" into the method that initiates the call, avoiding the actual method call, but in fact the inline process in the Java Virtual machine is far from simple. Because if not the immediate compiler did some special effort, according to the classic compilation Principle of optimization theory, most Java methods can not be inline!
Reasons that cannot be inline: only private methods that are called with the iinvokespecial directive, instance constructors, parent methods, and static methods that are invoked using invokestatic directives are parsed at compile time, except for the four methods described above. Other Java method calls require multiple selections of method receivers at run time, and all may exist in a version of the method receiver, in short, the default instance method in the Java language is the virtual method.

For a virtual method, when the compiler does inline, there is no way to determine which version of the method should be used, for example, the pre-optimization code:

Static Class B {

int value;

Final int get () {

return value;

}

}

public void Foo () {

y = B.get ();

z = B.get ();

sum = y +z;

}

Post-inline code:

public void Foo () {

y = b.value;

Do stuff

z = b.value;

sum = y + z;

}

B.get () inline is b.value, it is impossible to determine what the actual type of B is without a context, assuming that PARENTB and Subb have two classes with inheritance, and that the subclass overrides the Get () method of the parent class, The Get () method of the parent class or the Get () of the subclass. method, which needs to be determined at run time, cannot be concluded during compilation.

The Java language advocates the use of object-oriented programming, and Java object methods are virtual methods by default, so Java indirectly encourages programmers to use a large number of virtual methods to complete the program logic, internal union virtual method will create a "contradiction"? What should we do then?

To solve the problem of virtual method inline, the Java Virtual Machine design team has thought of a number of ways, first of all introducing a technique called "Type Inheritance Relationship analysis," a type analysis technique based on the entire application that determines whether an interface has more than one implementation in the currently loaded class. Information such as whether a class exists in a subclass and whether the subclass is an abstract class.

When the compiler is inline, if it is a non-virtual method, then directly inline can be, this is even when the inline stability guaranteed, if the virtual method will be queried to cha this method under the current program has more than one target version to choose, need to reserve an "escape gate", called Guardian Inline, If the virtual machine has not been loaded into a class that has changed the inheritance of the recipient of this method during the subsequent execution of the program, the inline optimized code can be used all the time, but if a new class is loaded that causes the inheritance relationship to change, then the compiled code needs to be discarded. Return to the interpretation state for execution, or recompile.

If the result of the query to cha is that there are multiple versions of the target method to choose from, the compiler will also make the last effort to use inline caching to complete the method inline, a cache that is built before the normal entry of the target method, which works roughly: the inline cache state is empty before a method call occurs. When the first call occurs, the cache records the version information of the receiver of the method, and the recipient version is compared each time the method call is made, and if the method recipient version of each incoming call is the same, then the inline can be used all the time, if the method receiver inconsistency occurs, This shows that the program really uses the polymorphic nature of the virtual method, and then cancels the inline and finds the virtual method table for the method dispatch.



4. One of the most advanced optimization techniques: Escape analysis

Escape analysis, like the analysis of type inheritance, does not directly optimize the means of code, but provides the basis for other optimization methods of analysis technology.

The basic behavior of the escape analysis is to analyze the object's dynamic scope: When an object is defined inside a method, it may be referenced by an external method, such as a call parameter passed to another method, which is called a method escape, and may even be accessed by an external thread. For example, assignment to a class variable or an instance variable that can be accessed in another thread is called a thread escape.

How to prove that an object does not escape to a method or thread, that is, the method or threads cannot access the object by any means, it is possible to perform some efficient optimizations for this variable, such as:

Stack allocation: In a Java Virtual machine, multiple rows of the Java heap allocate object memory, objects in the Java heap are shared and visible to each thread, and as long as the reference to the object is held, the object data stored in the heap can be accessed. The garbage collection system of a virtual machine can reclaim objects that are no longer used in the heap, but the recycling action takes time to filter recyclable objects, or to reclaim and defragment the memory. If it is determined that an object will not escape out of the way, it would be a good idea to have the object allocate memory on the stack, and the memory space occupied by the object can be destroyed as the stack frame stacks up. In general applications, the percentage of local objects that do not escape is very large, and if you can use the stack allocation, the large number of objects will be automatically destroyed as the result of the method, the garbage collection system will be much less stressful.

Synchronous elimination: Thread synchronization itself is a relatively time-consuming process, if the escape analysis can determine that a variable does not escape the thread, can not be accessed by other sites, then the read and write of this variable will not have competition, the implementation of this variable synchronization measures can be eliminated.

Scalar substitution: Scalar refers to the fact that a data can no longer be decomposed into smaller data, the original data types in the Java Virtual machine (such as numeric types such as int long and reference type, etc.) can not be further decomposed, they are called scalars, relative if a data may continue to decompose, Call it aggregation, the object in Java is the most typical aggregation, if a Java object is broken, according to the program access, the member variables used to restore the original type of access is called scalar substitution. If the escape analysis proves that an object is not being accessed externally and that the object can be disassembled, the program may not create the object when it is actually executed. Instead of directly creating a number of its members that are used by this method, after splitting the object, you can create conditions for further optimizations, in addition to allowing the object's member variables to be allocated and read and written on the stack.

JVM Optimization Technology

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.