Java code tips

You can improve message flow performance with Java™ by using some optimization techniques.

Before you begin

About this task

A significant proportion of the performance problems relating to Java are caused by memory and garbage collection issues, by interaction with external resources, and by Java code that could benefit from optimization. Follow these steps to identify and solve such performance issues:

The JavaCompute node enables you to include any valid Java processing, and it is common to reuse existing Java classes for specific functions. However, this code impacts the performance of the message flow, so ensure that any code used in this way is efficient.

Where possible, use the supplied nodes and functions of IBM Integration Bus to perform processing on a message, rather than recreating function that is already provided. For example, do not use a custom XML parser within the JavaCompute node. The XMLNSC parser that is provided with IBM Integration Bus is a high-performing parser that also offers validation against a schema, and the message tree that it generates can be used throughout the message flow. This is not the case with a custom parser with its own data structures.

Avoid starting new processes in the JavaCompute node to perform a specific piece of work. This is expensive in performance terms and results in additional CPU costs and an increased load on the system, because many short-lived processes are started and terminated when the work is completed. One of the benefits of the IBM Integration Bus runtime is that processes are long lived and initialization is minimized. This reduces total processing costs, because new processes are not started each time the message flow is invoked.

For information about tools that you can use to assess the current status of a running Java application, see developerWorks® IBM Monitoring and Diagnostic Tools for Java - Health Center Version 2.1.

Tree references

About this task

Avoid building and navigating trees without storing intermediate references. For example, the following code repeatedly navigates from root to build the tree:

MbMessage newEnv = new MbMessage(inAssembly.getMessage());
newEnv.getRootElement().createElementAsFirstChild(MbElement.TYPE_NAME, "Destination", null);
newEnv.getRootElement().getFirstChild().createElementAsFirstChild(MbElement.TYPE_NAME, "MQDestinationList", null);
newEnv.getRootElement().getFirstChild().getFirstChild().createElementAsFirstChild(MbElement.TYPE_NAME,"DestinationData", null);

However, it is more efficient to store references as shown in the following example:

MbMessage newEnv = new MbMessage(inAssembly.getMessage());
MbElement destination = newEnv.getRootElement().createElementAsFirstChild(MbElement.TYPE_NAME,"Destination", null);
MbElement mqDestinationList = destination.createElementAsFirstChild(MbElement.TYPE_NAME, "MQDestinationList",
    null);
mqDestinationList.createElementAsFirstChild(MbElement.TYPE_NAME,"DestinationData", null);

Java string concatenation

About this task

The + operator has a negative impact on performance because it involves creating a new String object for each concatenation; for example:

keyforCache = hostSystem + CommonFunctions.separator
+ sourceQueueValue + CommonFunctions.separator
+ smiKey + CommonFunctions.separator
+ newElement;

To improve performance, use the StringBuffer class and append method to concatenate java.lang.String objects, rather than the + operator, as shown in the following example:

StringBuffer keyforCacheBuf = new StringBuffer();
keyforCacheBuf.append(hostSystem);
keyforCacheBuf.append(CommonFunctions.separator);
keyforCacheBuf.append(sourceQueueValue);
keyforCacheBuf.append(CommonFunctions.separator);
keyforCacheBuf.append(smiKey);
keyforCacheBuf.append(CommonFunctions.separator);
keyforCacheBuf.append(newElement);
keyforCache = keyforCacheBuf.toString();

Java BLOB processing

About this task

If you want to process a BLOB (by cutting it into chunks or by inserting characters, for example), it is efficient to use a JavaCompute node with its strong processing capabilities. If you are using a JavaCompute node, use ByteArrays and ByteArrayOutputStream to process the BLOB.

Java manual garbage collection

About this task

Avoid manually invoking garbage collection, because it suspends the processing in the JVM, which significantly inhibits message throughput. In one example, a Java-based transformation message flow that was processing at the rate of 1300 messages per second without manual garbage collection was reduced to 100 messages per second when one manual garbage collection call was added to each message being processed.