Java code tips
You can improve message flow performance with Java™ by using some optimization techniques.
Before you begin
About this task
- Use the JVM resource statistics to review how much memory is in use by the JVM, and how often garbage collection is occurring in the integration server. For more information, see Resource statistics data: Java Virtual Machine (JVM).
- If you are calling external resources, review the elapsed time of the call.
- Review your Java code to identify any aspects that might benefit from optimization. There are several techniques that you can use to optimize the performance of your Java code in a message flow, including those described in the following sections:
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.