Message flow performance is reduced when you access message trees with many repeating records

Follow this guidance to resolve the problem of reduced performance in message trees that have repeating records.

Procedure

  • Scenario: Message flow performance is reduced when the following conditions are true:
    • You are using ESQL processing to manipulate a large message tree.
    • The message tree consists of repeating records or many fields.
    • You have used explicit SET statements with field reference paths to access or create the fields.
    • You have observed a gradual slowing of message flow processing as the ESQL processes more fields or repetitions.
  • Explanation: This problem occurs when you use field references, rather than reference variables, to access or create consecutive fields or records.

    Consider the following example, in which independent SET statements use field reference paths to manipulate the message tree. The SET statement takes a source and target parameter, where either or both parameters are field references:

    SET OutputRoot.XMLNS.TestCase.StructureA.ParentA.field = '1';
    The problem arises when the SET statement is used to create many more fields, as shown in the following example:
    SET OutputRoot.XMLNS.TestCase.StructureA.ParentA.field1 = '1';
    SET OutputRoot.XMLNS.TestCase.StructureA.ParentA.field2 = '2';
    SET OutputRoot.XMLNS.TestCase.StructureA.ParentA.field3 = '3';
    SET OutputRoot.XMLNS.TestCase.StructureA.ParentA.field4 = '4';
    SET OutputRoot.XMLNS.TestCase.StructureA.ParentA.field5 = '5';
    In this example, the five fields that are created are all children of ParentA. Before the specified field can be created or modified, the integration node must navigate the named message tree to locate the point in the message tree that is to be altered. For example:
    • To access field 1, the SET statement navigates to ParentA, then to the first field, therefore involving two navigations.
    • To access field 5, the SET statement navigates to ParentA, then traverses each of the previous fields until it reaches field 5, therefore involving six navigations.
    Navigating over all the fields that precede the specified field causes the loss in performance.
    Now consider a scenario that accesses repeating fields in an input message tree; for example:
    DECLARE myChar CHAR;
    DECLARE thisRecord INT 0;
    WHILE thisRecord < 10000 DO
    	SET thisRecord = thisRecord + 1;
    	SET myChar = InputRoot.MRM.myParent.myRepeatingRecord[thisRecord];
    END WHILE;  
    When index notation is used, as the count increases, the processing needs to navigate over all the preceding fields to get the one it wants; that is, it has to count over the previous records to get to the one that is represented by the current indexed reference.
    • When accessing InputRoot.MRM.myParent.myRepeatingRecord[1], one navigation takes place to get to the first record.
    • When accessing InputRoot.MRM.myParent.myRepeatingRecord[2], two navigations take place to get to the second record.
    • When accessing InputRoot.MRM.myParent.myRepeatingRecord[N], N navigations take place to get to the N-th record.
    Therefore, the total number of navigations for this WHILE loop is: 1 + 2 + 3 + .... + N, which is not linear.
  • Solution: If you are accessing or creating consecutive fields or records, use reference variables.
    When you use reference variables, the statement navigates to the main parent, which maintains a pointer to the field in the message tree. The following example shows the ESQL that can be used to reduce the number of navigations when creating new output message tree fields:
    SET OutputRoot.XMLNS.TestCase.StructureA.ParentA.field1 = '1';
    DECLARE outRef REFERENCE TO OutputRoot.XMLNS.TestCase.StructureA.ParentA;
    SET outRef.field2 = '2';
    SET outRef.field3 = '3';
    SET outRef.field4 = '4';
    SET outRef.field5 = '5';
    When referencing repeating input message tree fields, you could use the following ESQL:
    DECLARE myChar CHAR;
    DECLARE inputRef REFERENCE TO InputRoot.MRM.myParent.myRepeatingRecord[1];
    WHILE LASTMOVE(inputRef) DO
    	SET myChar = inputRef;
    	MOVE inputRef NEXTSIBLING NAME 'myRepeatingRecord';
    END WHILE;
    For further information, see Creating dynamic field references.