Create high-performance applications and servers using Java

zhaozj2021-02-17  55

Use Java to create high-performance applications and server content:

Memory access method

Extra synchronization

Additional objects create and garbage collection

Extra wrong check

General purpose library

Conclusion and future work

Research on a trial sexual

Sandeep K. Singhal

IBM T.J. Watson Research Center

Binh Q. Nguyen, Richard Redpath, Michael Fraenkel, Jimmy Nguyen

IBM Software Solutions

May 2001

Java has become the preferred programming language of dynamic web content due to Java's portability, ease of use and close combination with HTML. Java is used to generate animation effects on the webpage, select the server-side selection, format web content, and used as the front end of the transaction application to check the input information of the end user. Java is also an important language for designing 3D actions in a virtual reality model (VRML) [HW96] language and provides multi-user interaction in this virtual environment [VRML97].

In addition to the above mentioned features, Java is rarely used to develop applications and servers that require high performance and high throughput. Developers rarely choose Java's main reason for the main reason for the program compiled by the Java code (such as C or C or C or C ). The limitations of garbage collection and JIT (Just-in-Time) in large-scale procedures also cause suspicion of developers to Java performance.

We combine carefully programming and targeted optimization, which has been overcome many of these aspects. This article describes the use of Java to develop high-throughput applications and servers and describes the performance of the Java application and its convenient to achieve traditional languages ​​such as C and C , and written code. These results are built on our experience gained using the Java Development Inverse (Interactive Universe) server.

Our test environment is a Pentium 150MHz computer with 48MB of memory, running Windows 95, using the Java 1.1.4 compiler and virtual machine provided by Sun, and optimized compilation with the -O flag. Time is obtained by performing a target code in a tight loop and calling system.currentTimeMillis () capture timing information. We also use the Just-IN-TIME (JIT) code generator (converting Java Byte code to a local directive) to test.

Other chapters describe some of the main performance issues encountered by Java application developers, as well as methods of optimizing these issues: memory access methods, additional synchronization, additional objects, and garbage collection, additional error handling and general class libraries Dependence. Although these more content adapt to other object-oriented programming languages, it has a close relationship with Java developers. The end of the article describes how the overall performance of the INVERSE server application will be improved by optimizing these aspects, and discussing future work in this area.

Memory access method

In the case where the current processor speed and memory access time gap are increasing, the developers of high-performance applications are increasingly clearly clearly realized to minimize the importance of memory access time. In compilation languages ​​such as C , since the memory address is pre-calculated, the memory access time is almost the same for different variables. The worst case is just a indirect addressing. However, for Java, the efficiency of the application is considerably accessed by the type of variables and the impact of access. For example, stack variables can be directly addressed, while instance variables generally require additional indirect addressing processes.

Read and write

No jit

Local method variable

Example variable of object

Parent class instance variable

Parental instance variable

Class static variable 1.00

1.92

1.96

1.83

1.23 1.00

2.4

2.4

2.4

1.52

Jit

Local method variable

Example variable of object

Parent class instance variable

Semiotactivation variable of superfather instance variables 1.00

1.64

1.73

1.73

1.23 1.00

1.99

2.4

2.21

1.62

Table 1 shows that the access time of the instance variables, the current class and the parent class, and the number of static class variables are shown in the table, and the read / write speed of the local method variable is fast, and The read and write speed of the static variable is compared to the instance variable. This difference is more obvious in the case of JIT. Although other access types are different, they are very different, and they are not discussed here. This mode of variable access time tells us that dynamic data address translation has high practical value.

Table 1: Access time for different variable types and access modes

Extra synchronization

In Java, a method (Method) or code block may be labeled with SYNCHRONIZED. In the same class, any synchronization method cannot perform multi-threaded operation, and for an object as a parameter, a synchronized code segment is considered a method of synchronization. To support this capability, Java virtual machines are connected to a monitor (Monitor) on an object with a synchronization method. When there is a thread entering a synchronized code

When it is, it needs to get a lock tag from the monitor to be non-synchronized. Synchronize.

WITHOUT JIT

Wireless

Thread preemptive 0.54

0.55 3.96

8.87

With Jit

Wireless

Thread seller 0.50

0.57 5.55

11.00

Table 2:

Whether synchronous and wireless

Method call time in different combinations

(Microsecond)

As shown in Table 2, the synchronization method can cause the operation of the application to be about 20%. The table is shown in different combinations of time to call the time used. In the case of thread preemption, the two threads accessed this object in a close cycle.

The data in the table reveals such a phenomenon: adding synchronous markers in the program to reduce performance by 8% to 11%. This is still a single thread (ie the monitor never interrupts the thread). It can be seen that the synchronization method is not just a lock mark, and more time spent on the check lock mark.

It should also be noted that the JIT compiler does not enhance access and preempting loss of lock tags. This is because it doesn't get information about the application structure, in fact, because the JIT compiler's loss, the running of the program slowed down. In contrast, in the case of an asynchronous call, it can slightly enhance the efficiency of the program.

Synchronization The impact on program efficiency is subtle, for example, when memory allocation synchronization, it means that an object will be reduced.

Many general functions in the Java class library are designed as threads, so it is synchronized. For example, an element that accesses an index in the vector needs to call a synchronized method. Just like called nextItem () in the associated enumeration type. With our experience, many collections have only one thread to access, so this is due to small loss. In order to make our app to be selective mask synchronization, we created subclasses like Java Vector to provide non-synchronous access methods. The situation is similar in the I / O stream library. 86% loss from the data of the data of the OutputStream method for synchronization is used in the use of DataOutputStream read and write. Here we cannot cancel synchronization, but sometimes use the method to add multiple synchronous methods to the method to increase efficiency in a synchronous code block.

For example

For (i = 0; i

x.f (); // synchronized on x

Rewrite

SYNCHRONIZED (X) {

For (i = 0; i

x.f (); // synchronized on x}

The replacement code allows the synchronization method of the Java virtual machine "short circuit". This approach is only used when the synchronization method is very short. Otherwise it will block other threads. Or use when there is no thread. However, the Java virtual machine will result in a significant difference in the backup efficiency of the lock mark.

Additional objects creation and garbage collection

With the Java's built-in garbage collection mechanism, the programmer no longer needs to worry about how their application needs to be assigned and when it is released. Although this mechanism simplifies the task of OO development, it also brings a significant efficiency issue. Programmers like to create objects at will, because they mistake to do this very "cheap", and in fact, Java virtual machine wants them to pay for object memory allocation and release. The creation of objects and destroyed in Java is expensive. Table 3 shows the time required for different object creation operations and extracting entries from a synchronized array (like it is in a free object pool). The table reveals that the creation of the object is much more expensive than the existing objects. There are about 1/10. This is because, from our experience, many temporary classes are instantiated in the program.

Not

JIT JIT

Create an object (unconformable function)

Create an object (with constructor)

Create a subclass (unconformable function)

Create a subclass (base class constructor) 12.57

12.97

12.79

12.80 12.36

13.45

12.47

12.53

(Synchronous) Remove Element 4.06 3.84 from an array

TABLE 3:

Create a Java object

time

(Microsecond)

In an integrated application, such as the server, the creation of objects has a significant impact. The garbage collector should be performed only when there is no other thread runtime to minimize the impact of its application efficiency. However, a high-performance application may not cause such a wait for aperture, so the garbage collector is also "stealing" time when the application is executed.

In order to reduce the objects created and destroyed, we used the following two techniques:

When an object is repeated (eg, in a specific method), a static variable is declared between the loop of this method to store this object. The reinitialize () method is called in the method to initialize the reinitialize () method. When an object is a plurality of active examples, and their life cycle cannot be used as a single part in the app, use a vector or an expandable array as a free instance library. When an object is no longer needed, use a static method to add it to the free object pool. Similarly, when a new class instance is to be obtained, another static method is called from the library to release an existing instance and call the reinitialize () method. Declaring its constructor as private to place an instance directly to it directly.

Both methods rely on the reinitialize () method in the optimized class. Occasionally we also need to create such support in the Java class that does not support this skill.

Error check excessive

The Java virtual machine provides local support for exception processing. The C is different from this, and it relies on the instructions generated by the compiler to store and process exception information. Java these built-in instructions make Java's exception processing speeds. As shown in Table 4, the time consumption caused by the joining the try-catch clause is insignificant. Although the time required to deal with the exception is not small, this cost is only accidentally appeared.

No JIT JIT

Function call

Function call in TRY-CATCH (no exception thrown)

Try-catch's function call (with exception thrown) 0.2

0.2

191.7 0.2

0.2

186.2

IF-Test Array Index Bounds

Array Dereference

Array Dereference Throwing Bounds Exception 0.5

0.4

1613.2 0.5

0.4

1548.9

IF-Test Using InstanceOf

Object Type Cast

Object Type Cast Throwing Casting Exception 0.8

0.7

1581.9 0.7

0.7

1469.8

Table 4:

Java exception handling

Time consumption

(Microsecond)

Try-catch clauses are close to zero time consumption tell us that we should rely on exception processing instead of making a clear error check. For example, as follows: IF ((idx> = 0) && (IDX

X = array [idx];

Else

// Error

If it relies on exception processing, the program will look like this:

Try {

x = array [idx]

}

Catch (arrayoutofboundsexception e) {

// Error

}

Under normal case (index is within the range of value), the program for exception processing is about 50% faster than the ordinary method. As long as the usual situation is more than exception, the efficiency of the application has improved. This is particularly correct in the case of cycling. The situation is similar when performing a strong type conversion, using InstanceOf, not as high as capturing ClassCastException efficiency.

Try-catch lets us redefine the use of exceptions in high-performance applications. In addition to simply indicating errors, exception is also used to indicate all non-usual situations, even if these non-usual situations are sometimes not errors. This method is common to "Making The Common Case Fast.".

General class library

Standard Java Class libraries support many types of applications, from simple web applets to a more complex system. But just like all software, this general class library does not provide optimal performance for certain specific applications. Recognizing that the performance can be improved by improving JDK's universal frameworks. Optimization of certain classes is optimized on the application's access to the access form and class of the application.

Optimization of certain methods in the Java class library must sacrifice the performance of other methods. The designer should take the usage of these methods based on the application. If the application mainly calls unopened methods, you should change the implementation of the class to improve performance. For example, we have written a HashTable connected to the List to support high-speed serial access.

Like other class libraries, JDK is seriously on its interface. This method enhances modular, but sacrifies some overall performance. For example, because the classes can only be interacted through a general interface, they cannot use similar to each other in implementation to improve performance. When a particular class interacts through such an interface, the effect can be improved by changing the method of setting the interaction point. For example, we merge ObjectOutputStream and ByteArrayoutputStream to provide fast asynchronous output to the BYTE array.

Conclusion and prospects

In the process of developing high-performance servers, we discovered several optimization methods for Java virtual machine characteristics:

Rely on re-implementing standard Java classes to remove synchronization in applications

Develop user-working standard Java classes to cooperate with memory access mode in your application.

Merged Java class when interaction can optimize

Execution of ordinary cases, use exception processing to speed up the speed.

Reuse objects of objects, do not create new temporary instances.

Buffer onClusion and Future Work with reference to the reference variable when possible

Before instator

Inverse PKTS / Sec Processed:

1 User

10 Users

100 User $ 145

99

N / A 810

505

147

Base Limits (Java)

1 User

10 Users

100 Users 930

93

9

Base Limits (C)

1 User

10 Users

100 Users 1080

108

11

Table 9:

Optimization of Inverse Performance

(Packets / Second

Processing throughput)

And Comparison TO

Zero-Processing Capabilities

Thank you

Here, I would like to thank the James Clinton. Thank you for your feedback from our previous version. Reference book

[AG96] K. Arnold and J. Gosling. The Java Programming Language (Reading, Massachusetts: AddIn WeSley), 1996.

[C96] d. cheriton. Object-oriented programing from a modeling and simulation perspective. To Appear ..

.

[K97] Eugene Koznetsov. "Optimizing Performance Execution with Java." Java Report 2.6 (June 1997), 49-51.

[LY97] T. Lindholm and F. Yellin. The Java (Reading, Massachusetts: Addison-Wesley), 1997.

[S 97] S. Singhal, B. Nguyen, R. Redpath, J. Nguyen, And M. Fraenkel. "Inverse: Designing An Interactive Universe Architecture for Scalability and Extensbility."

[VRML97] VRML Architecture Group. "Living Worlds: Specification and Comments." February 1997.

转载请注明原文地址:https://www.9cbs.com/read-30852.html

New Post(0)