question

Upvotes
Accepted
15 3 1 4

Channel::read behavior

I am using the Elektron ETA SDK for Java, v. 3.1.1.L1. Having subscribed to a RIC, I have observed that, when notified by the Selector of an OP_READ operation, Channel::read returns null most of the time, with ReadArgs::readRetVal having a positive value. According to the documentation, this indicates that a full TransportBuffer is not available yet, but that there are more bytes to be read, so Channel::read should be called again. Doing so eventually yields a full TransportBuffer.

My concern relates to the frequency this occurs. As an example, for an incoming full TransportBuffer rate of 2K/sec, I receive around 250K/sec of responses returning null with a positive readRetVal, which I promptly ignore, since there is no processing that is needed for those.

Is this expected, and if so, is there way to suppress such responses, to save on unnecessary processing?

elektronrefinitiv-realtimeelektron-sdkrrteta-apielektron-transport-api
icon clock
10 |1500

Up to 2 attachments (including images) can be used with a maximum of 5.0 MiB each and 10.0 MiB total.

1 Answer

Upvotes
Accepted
38.1k 71 35 53

From my test, this scenario usually happens when the payload in the retrieved message is huge, such as the payload of data dictionary domain.

In the example code, ChannelSession::readInt(...) method has a do/while loop which calls the read method while the readArgs.readRetVal() is more than TransportReturnCodes.SUCCESS (0).

private int readInt(PingHandler pingHandler, ResponseCallback callbackclient, Error error)
    {
        TransportBuffer msgBuf;
        do /* read until no more to read */
        {
            msgBuf = channel.read(readArgs, error);
...

        }
        while (readArgs.readRetVal() > TransportReturnCodes.SUCCESS);
...
}

Channel.read() method not only reads the raw data from network but it also processes the raw data and returns the buffer.

When the returned buffer is null and readRetVal return a value which is more than zero, it indicates the more raw data needs to be read from the network in order to create the complete buffer.

The code is designed to do this as fast as possible. Therefore, it is possible that the read method method is called too fast without reading any raw data from the network. You can verify this by print readArgs.uncompressedBytesRead() and readArgs.readRetVal() when the returned buffer is null.

You can see that there are a lot of calls that uncompressedBytesRead returns zero.

### Read return null: uncompressedBytesRead: 0, readRetVal:3472
#### Read return null: uncompressedBytesRead: 0, readRetVal:3472
#### Read return null: uncompressedBytesRead: 0, readRetVal:3472
#### Read return null: uncompressedBytesRead: 0, readRetVal:3472
#### Read return null: uncompressedBytesRead: 6138, readRetVal:2142
#### Read return null: uncompressedBytesRead: 6130, readRetVal:152
#### Read return null: uncompressedBytesRead: 0, readRetVal:152
#### Read return null: uncompressedBytesRead: 0, readRetVal:152
#### Read return null: uncompressedBytesRead: 0, readRetVal:152
#### Read return null: uncompressedBytesRead: 0, readRetVal:152
#### Read return null: uncompressedBytesRead: 0, readRetVal:3624
#### Read return null: uncompressedBytesRead: 0, readRetVal:4292
#### Read return null: uncompressedBytesRead: 0, readRetVal:4292
#### Read return null: uncompressedBytesRead: 0, readRetVal:4292
#### Read return null: uncompressedBytesRead: 0, readRetVal:4292
#### Read return null: uncompressedBytesRead: 0, readRetVal:4292
#### Read return null: uncompressedBytesRead: 0, readRetVal:4292
#### Read return null: uncompressedBytesRead: 0, readRetVal:4292
#### Read return null: uncompressedBytesRead: 0, readRetVal:4292
#### Read return null: uncompressedBytesRead: 6138, readRetVal:2294

From the code, this is expected because it is designed to get the buffer as fast as possible.

However, if you would like to avoid this, you can add a short sleep for this condition. This can reduce the number of channel read called.

if(msgBuf == null && readArgs.readRetVal() > TransportReturnCodes.SUCCESS){
try {
	Thread.sleep(5);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
 e.printStackTrace();
 	}
 }
#### Read return null: uncompressedBytesRead: 6138, readRetVal:2142
#### Read return null: uncompressedBytesRead: 6130, readRetVal:47072
#### Read return null: uncompressedBytesRead: 6138, readRetVal:40934
#### Read return null: uncompressedBytesRead: 6138, readRetVal:34796
#### Read return null: uncompressedBytesRead: 6138, readRetVal:28658
#### Read return null: uncompressedBytesRead: 6138, readRetVal:22520
icon clock
10 |1500

Up to 2 attachments (including images) can be used with a maximum of 5.0 MiB each and 10.0 MiB total.

Thank you for the detailed explanation, that makes sense.

Click below to post an Idea Post Idea