|
i've read a lot of benchmark that ibmers say that they've achieved like Volano, SPECjbb2000, and the result is good but i am not sure that is it perform the same with all the iseries server http://www.spec.org/osg/jbb2000/results/jbb2000.html . anyway it is good to hear things all people's experience in running java app. in iseries. maybe this could help (ps:if you have read this or a newer version, just ignore it :) AS/400 Java Performance Tuning (for V4R2) Tips (or go to :http://www-919.ibm.com/developer/java/faq/perffaq.html#1) AS/400 Java Performance Tuning (for V4R2) Tips Introduction You asked for it, and now it is here. The AS/400 Java Performance Tips. Keep watching this page as it evolves. If you have any questions, or would like to share a tip, use the "Feedback" button at the top of this page. Table of Contents Top Tips Load the latest CUM package and PTFs Use CRTJVAPGM on .zip and .jar and .class files Use the native JDBC driver or ToolBox record I/O for local AS/400 data access Leave GCHMAX as default; Adjust GCHINL and GCHPTY as necessary; Ignore GCHFRQ Minimize the use of String Objects Minimize object creation Minimize synchronized methods Use Prepared Statements AS/400 Java Tips Load the latest CUM package and PTFs Use CRTJVAPGM on .class files Use CRTJVAPGM on .zip and .jar files Java Language Performance Tips Minimize synchronized methods Use the -O javac option Minimize object creation Minimize the use of String objects Leverage variable scoping Minimize use of exceptions Minimize JVM start up Use static final when creating constants AS/400 Database Access Tips Use the native JDBC driver Use Prepared Statements Store character data in DB2 as Unicode Store numeric data in DB2 as float Use ToolBox record I/O Check ToolBox for existence of a Java program object Close statement objects before recreating similar statements Use getField() rather than getFields() in Toolbox recordaccess Use get...(int columnIndex) rather than get...(String columnName) Garbage Collection Tips Leave GCHMAX as default Adjust GCHINL as necessary Adjust GCHPTY as necessary Ignore GCHFRQ Monitor GC Heap faulting Introduction | Table of Contents | The Good Stuff !! ---------------------------------------------------------------------------- ---- The Good Stuff AS/400 Java Tips Load the latest CUM package and PTFs To be sure that you have the best performing code, be sure to load the latest CUM packages and PTFs for all products that you are using. Information on the AS/400 JVM can be found at the Developer Kit for Java Web Site. Information on the IBM Toolbox for Java can be found at the Toolbox Web Site. Use CRTJVAPGM on .class files Java .class files should be converted into direct execution (machine instruction) Java program objects through the CRTJVAPGM command. Use this command before running any Java programs. The Program object is permanent and will be re-used once it is created. Use the DSPJVAPGM command to determine if the Java Program Object exists. Optimization levels 10,20,30 and 40 are supported on the CRTJVAPGM command Relative Performance: Results will vary by application. For computation and call intensive applications the relative gains can be dramatic. Here are the relative performance gains for Towers of Hanoi. Relative time Optimization level 40 1.00 Optimization level 30 1.73 Optimization level 20 2.02 Optimization level 10 2.65 Interpretive 12.95 Comparisons based on v4r2. JDK 1.1.4. Use CRTJVAPGM on .zip and .jar files CRTJVAPGM must be used on .zip and .jar files. If the CRTJVAPGM was not run, the JAVA/RUNJVA command will implicitly create program objects for each class file in a .zip or .jar. Unlike a .class file however, these program objects are not saved. The implicit creation of program objects will significantly impact JVM startup or class loading. The implicit creation will occur every time you start the JVM. To determine if your .zip/.jar file has a permanent program object use the DSPJVAPGM command. NOTE 1: Packaging multiple classes in one .zip or .jar file may also improve class loading time and code optimization. NOTE 2: If using the IBM Toolbox for Java classes on v4r2, you will need to perform CRTJVAPGM on jt400.zip and jt400.jar. Java Language Performance Tips Minimize synchronized methods Synchronized method calls take at least 10 times more processing than a non-synchronized method call. Synchronized methods are only necessary if you have multiple threads sharing the same object. If you share objects between threads, keep the duration of the synchronized method low to improve parallel execution. Use the -O javac option The javac compiler may in-line methods if the -O option is selected. In order for a method to be in-lined it must be a final method (static, final, or protected). Final methods can not be subclassed, which is the key to allowing in-lining. Method in-lining is not supported in the AS/400 JVM other than through the -O option. Minimize object creation Object creation can occur implicitly within the Java api's that you use as well as within your program. Object creation and the resulting garbage collection can typically take 15% of a server transaction workload. To minimize this cost you can reuse objects by implementing a "reset" method that clears the local variables in the object. The code fragment if objx = null then objx = new x(); else objx.reset(); can provide significant performance improvements. Minimize the use of String objects String objects in Java are immutable. This means that you can not change (append, etc.) to a string object without creating a new object. Object creation is expensive and can occur multiple times for each String object you are using. To minimize the use of String objects you should use either StringBuffer or Char[]. StringBuffer may also be a problem since the StringBuffer classes use synchronized method calls. An array of characters (char[]) can be used to simulate fixed length strings. This is recommended for applications which make heavy use of string data. Relative Performance: The following table shows the relative performance difference when using String, StringBuffer, or char[]. The test case concatenates two strings. For the char[] case. the concatentation reduces to simple array assignment, thus avoiding the creation of objects and the synchronization overhead associated with StringBuffer. In the following table the String "World Wide" was concatenated to the string "Wait". For the Char[] test there were simply four char[] assigments for the characters 'W' 'A' 'I' 'T'. Relative time char[] 1 StringBuffer 35 String 363 Comparisons based on Optimization level 40, v4r2. JDK 1.1.4. Leverage variable scoping Java supports multiple techniques for accessing variables. One typical technique is to write an "accessor" method. Local variables are the fastest. Relative performance: Here are five comparisons on variable access time and their relative performance. A local variable is the fastest and is given a relative performance of 1. Relative time Local variable : 1.0 Instance variable: 2.0 Accessor method in-lined: 2.0 Accessor method: 5.9 Synchronized accessor method: 99.6 Comparisons based on Optimization level 40, v4r2. JDK 1.1.4. Minimize use of exceptions In v4r2 Java exceptions use the full ILE exception handling mechanism. This is a relatively expensive operation. Significant improvements are planned in the next release. As with any JVM however, exceptions should be used for error conditions that occur infrequently. Minimize JVM start up The JAVA/RUNJVA commands create a new batch immediate Job to run the JVM. Limit this operation to relatively long running Java programs. If you need to invoke Java frequently from non-Java programs consider passing messages through an AS/400 Data Queue. The ToolBox Data Queue classes may be used to implement "hot" JVM's. Use static final when creating constants When data is invariant, declare it as static final. For example here are two array initializations: class test1 { int myarray[] = { 1,2,3,4,5,6,7,8,9,10, 2,3,4,5,6,7,8,9,10,11, 3,4,5,6,7,8,9,10,11,12, 4,5,6,7,8,9,10,11,12,13, 5,6,7,8,9,10,11,12,13,14 }; { class test2 { static final int myarray2[] = { 1,2,3,4,5,6,7,8,9,10, 2,3,4,5,6,7,8,9,10,11, 3,4,5,6,7,8,9,10,11,12, 4,5,6,7,8,9,10,11,12,13, } 5,6,7,8,9,10,11,12,13,14 }; Relative Performance: When 10,000 objects of type test1 and test2 were created the relative time for test1 was about 2.3x longer than test2. The test saved each array object to avoid any garbage collection. Comparisons based on Optimization level 40, v4r2. JDK 1.1.4. AS/400 Database Access Tips Use the native JDBC driver There are two AS/400 JDBC drivers that may be used to access local data. The Toolbox driver is located at URL "jdbc:as400:system-name" where system-name is the AS/400 tcp/ip system name. The native JDBC driver is located at URL "jdbc:db2:system-name" where the system-name is the Data Base name. The native AS/400 JDBC driver uses an internal shared memory condition variable to communicate with the SQL/CLI Server Job. The ToolBox JDBC driver assumes that the data is remote and uses a socket connection into the client access ODBC driver. The native JDBC driver is faster when you are accessing local data. Use Prepared Statements The JDBC prepareStatement should be used for repeatable executeQuery or executeUpdate methods. If prepareStatement is not used, the execute statement will cause an implicit prepareStatement every time the execute statement is run. Store character data in DB2 as Unicode The AS/400 JVM stores string data internally as 2 byte Unicode. If you are reading or writing large amounts of string data and the data is stored in EBCDIC, the data will be converted on every database access. You can avoid this conversion by storing the data in DB2 as 2 byte Unicode. Use the SQL graphic type with CCID 13488 or the DDS grahic type with CCID 13488. Store numeric data in DB2 as float Decimal data can not be represented in Java as a primitive type. Decimal data is converted to the abstract class Java.lang.BigDecimal on every database read or write. This conversion can be avoided by storing numberic data in the database as float or double. Alternatively, you may considering converting the BigDecimal type to float for heavy calculations while leaving the Database in decimal form. Note that rounding differences may be introduced with the use of float or double. Use ToolBox record I/O The IBM Toolbox for Java provides native record level access classes. These classes are specific to the AS/400 platform. They provide a significant performance gain over the the use of JDBC access. Check ToolBox for existence of a Java program object The jt400.jar file contains the IBM Toolbox for Java product. After installation, this .jar file does not have a Java program object. Use the CRTJVAPGM at optimization level 40 to create the program object. See tip #3. Use the CRTJVAPGM command during low system activity as it will take some time. Use the DSPJVAPGM command to see if the program object already exists. Close statement objects before recreating similar statements The AS/400 attempts to reuse SQL cursors by constructing a cursor cache. Normally a cursor is created for each unique query as part of the executeQuery or executeUpdate methods. Cursors are available for reuse if they are not actively attached to a statement object. If you use the close() method on a statement, it makes the associated cursor eligible for reuse. This reuse can save a large amount of processing and is similar to sharing open files in RPG. A statement object may be eligible for garbage collection if you no longer hold a reference to that object. Garbage collection will implicitly close the statement, thus making the cursor elibible for reuse. Garbage collection points vary by application. It is better to close() the statement than to assume that cursor reuse will occur implicitly. Use getField() rather than getFields() in Toolbox recordaccess The ToolBox record class supports retrieving individual fields through getField() or all of the fields through getFields(). On a file with 9 packed decimal fields, 10 character fields, and one date field the second loop takes about 2 times longer than the first loop. Since most applications do not need all of the fields in a record. It is better to use getField on only the fields used by the application. partialKey[0] = new BigDecimal("-2"); partialKey[1] = new BigDecimal("-5"); // for (int i = 0; i < RowCntArg; i++) { partialKey[0] = ((BigDecimal)partialKey[0]).add(EIGHT); ... tablexdata = file.read(partialKey); // reads record no conversion ... { Object[] fieldobj = null; for (int i = 0; i < RowCntArg; i++) { partialKey[0] = ((BigDecimal)partialKey[0]).add(EIGHT); ... tablexdata = file.read(partialKey); ... fieldobj = tablexdata.getFields(); // Will convert every field to a Java type ... { Use get...(int columnIndex) rather than get...(String columnName) Depending on the number of columns in your result set,a getxx field operation using the columnIndex is about 2 times faster than a getxx field operation using the columnName. There is an application consideration however when using getxx columnIndex in that your application becomes more dependent on the order of the columns in the result set. Note that on some JDBC drivers, the retrieval of columns by index is limited to ever increasing index values. This is not a restriction on AS/400 JDBC drivers. Garbage Collection Leave GCHMAX as default The GCHMAX parameter on the JAVA/RUNJVA command specifies the maximum amount of storage that you want to allocate to the garbage collection heap. In general the default value (set to the largest possible value) should be used. The system does not allocate the storage until it is needed. A large value should not impact performance. If this maximum is reached, the JVM will stop all threads and attempt to synchronously collect objects. Setting this value to a small number may force unnecessary synchronous collections. Adjust GCHINL as necessary The GCHINL parameter on the JAVA/RUNJVA command specifies the amount of initial storage that you want to allocate to the garbage collection heap. This parameter indirectly affects the frequency of the asynchronous garbage collection processing. Each time the total allocation for new objects reaches this value, asynchronous collection is started. This parameter is application dependent and may require some adjustment. Adjust GCHPTY as necessary This parameter affects the relative priority of the garbage collection thread. A higher priority value will reduce the amount of time spent in the asynchronous portion of the collection. You should not adjust this value unless the application is memory constrained. Ignore GCHFRQ This parameter is not used. It has no effect on performance. Monitor GC Heap faulting Java objects are maintained in the JVM heap. Excessive page faults may occur if the memory pool for your JVM is too small. These faults will be reported as non-database page faults on the WRKSYSSTS command display. Typically the storage pool for your JVM is *INTERACT. Fault rates between 20 and 30 per second are acceptable. Higher rates should be reduced by increasing memory pool size. Introduction | Table of Contents | The Good Stuff !! About IBM | Privacy | Legal | Contact
As an Amazon Associate we earn from qualifying purchases.
This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].
Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.