Ibm just-In-Time Compiler (jit) for Java: Best Practices and Coding Guidelines for improving Performance



Yüklə 153,14 Kb.
Pdf görüntüsü
səhifə4/7
tarix07.11.2018
ölçüsü153,14 Kb.
#78937
1   2   3   4   5   6   7

 

 

 



However, in Figure 6, the character x is directly appended to the StringBuilder object that str points to

and no objects are created.  

public class myClass { 

 

public static int N = 10000; 



public static void main(String [] argv) { 

StringBuilder str = new StringBuilder(); 

for (int i = 0; i < N; i++) 

   str.append(“x”); 



Figure 6. Example of avoiding unnecessary allocations: More efficient version of Figure 3a, no new objects created 



 

Figure 7 shows the performance of the examples shown in Figure 4, Figure 5 and Figure 6. As you 

can see, the performance improvements are significant when allocations are avoided inside loops. All 

performance measurements that are mentioned in this paper were obtained on an IBM System x™ 

machine using Intel® Xeon™ Quad Core system running at 3.2 GHz with 8 GB of RAM. 

Here are a few guidelines to improve the locality of the Java application: 

 

Carefully design the application’s class hierarchy. It is better to place less data in the super 



classes, unless all the subclasses in the hierarchy access the data. This greatly reduces the 

size of the objects. 

 

Move rarely used field members into separate classes. Although this can increase the 



memory footprint of the Java application, this separation has benefits in the form of reduced 

cache misses. 

 

Try to avoid the unnecessary creation of objects. Instead, you should design the application 



so that it reuses objects when possible. If the application is multithreaded, you can use 

thread-local data for temporary buffers. In fact, use the ThreadLocal class wherever possible. 



IBM Just-In-Time Compiler (JIT) for Java 

Best practices and coding guidelines for improving performance 


 

 

 



 

Figure 7. Performance of string concatenation 

Guideline: Minimize object allocations, if possible 

Minimizing the number of objects that an application allocates also improves the locality of the 

application. Objects reside more often in the lower levels of the memory hierarchy (cache), which 

results in better application performance. However, you should avoid the allocation of a large number 

of short-lived objects, as this tends to result in poor cache locality of the application. If you need to 

create short-lived objects, then the recommendation is that you use the IBM JDK’s generational 

garbage collection policy (-Xgcpolicy:gencon) [10].  

As explained in the previous section, the TRJIT compiler tries to aggressively convert heap 

allocations to stack allocations through an optimization called escape analysis [3]. When possible, 

you can follow a few guidelines when writing Java application code to facilitate the stack allocation of 

objects. In the following cases, the TRJIT compiler cannot convert a heap allocation into a stack 

allocation: 

 

An object escapes if it is stored into a static field or a field of another object.  



 

If the object allocation is passed as a parameter into a method call that cannot be inlined. 



 

If the allocation is returned from a method call that cannot be inlined. 



IBM Just-In-Time Compiler (JIT) for Java 

Best practices and coding guidelines for improving performance 


 

 

 



 

At lower optimization levels, the TRJIT compiler does not perform this optimization. 



Reducing the number of allocations also reduces the load on the J9 JVM garbage collector. There are 

fewer objects on the heap, which results in fewer garbage collections, in turn reducing the pause 

times of the application. A last point to be noted here is about memory leaks. To avoid memory leaks 

in the application, release any references to obsolete objects (by storing a NULL into such 

references). References from static fields or objects with a long life time are not garbage collected 

until the application ends.  



Guideline: Use immutable fields 

The TRJIT compiler aggressively optimizes immutable fields. You can follow these guidelines to 

make fields immutable: 

 



Declare fields as final when possible. 

 



Declare fields as private and write to such fields only in constructors. 

When an object is declared as final static, the TRJIT compiler can apply optimizations based on an 

analysis of the contents of the object on the heap. For example, the TRJIT compiler can determine 

the length of an array, which can help optimize loops that iterate over the array. (Note: Java has no 

way to declare multidimensional arrays to be final — only the first dimension of a final array is fixed.) 

Methods 


As explained in the previous section, the TRJIT compiler attempts to focus optimization efforts on the 

most frequently run parts of the application. Therefore, a method that is invoked frequently has a much 

greater chance of being optimized aggressively, as compared to a method that is only invoked a few 

times. It is also beneficial to structure the Java application so that most frequently run methods (hot

invoke other frequently run methods, rather than infrequently run (cold) methods. This helps the TRJIT 

compiler to aggressively inline method calls within hot methods. 



Guideline: Keep methods small 

From a Java development perspective, it is advantageous to keep methods small (about 10 lines of 

Java code), as this allows the TRJIT compiler to inline callee methods into their callers. Some 

heuristics are outlined in this paper because they cause a call more likely to be inlined by the TRJIT 

compiler: 

 



Calls in loops: The inlining of method calls within loops is likely to benefit performance. 

 



Specialized calls: Calls that have constant arguments and arguments with a specific type 

(rather than a generic type) are more likely to be inlined.  

You should declare parameters to method calls to be of a final or leaf type in the class hierarchy of 

the Java application. This allows the TRJIT compiler to optimize virtual calls on such parameters by 

devirtualizing, without using a virtual guard. If parameters are declared to be Object or an abstract or 

interface type, then the compiler might not be able to optimize virtual calls as effectively. Because 

devirtualization is important for optimizations of the Java code, keep the class hierarchy as simple as 

possible to allow the TRJIT compiler to devirtualize as many call sites as possible. 



IBM Just-In-Time Compiler (JIT) for Java 

Best practices and coding guidelines for improving performance 


Yüklə 153,14 Kb.

Dostları ilə paylaş:
1   2   3   4   5   6   7




Verilənlər bazası müəlliflik hüququ ilə müdafiə olunur ©genderi.org 2024
rəhbərliyinə müraciət

    Ana səhifə