Resources | developer.brewmp.com Resources | developer.brewmp.com

Developer

resources

Use of ISockPort_Read() and ISockPort_Readable() for max throughput

The ISockPort interface provides two methods for downlink traffic: ISockPort_Readable() and ISockPort_Read(). ISockPort_Readable() allows an application to register a callback to be notified when data is available for reading on a socket. ISockPort_Read() gets the data from the socket.

A common implementation using ISockPort might include the following psuedocode:

myDownloadFunction()
{
    ISockPort_Readable(myReadableCallback);
}
 
myReadableCallback()
{
    while (AEE_NET_WOULDBLOCK != ISockPort_Read())
    {
        // got some data!  immediately try for more.
    } 

    // oops, no more data. re-register ourselves.
    ISockPort_Readable(myReadableCallback);
}

These methods have certain costs:

  • ISockPort_Readable() takes time to both register and execute the callback function. It is minor, but still worth noting.
  • ISockPort_Read() execution time is (relatively) fixed, so it has a time penalty even when it does not transfer as much (or any) data.

It is advisable to design a Brew MP application's network integration layer such that the overall number of calls to each method is minimized. Avoid calling Read and Readable for each incoming packet. This is because ISockPort_Read() will usually get all waiting data on the first try, so in this approach, every packet has the overhead of a failed Read and an additional Readable callback registration.

By including a timer between the ISockPort_Read() calls, multiple TCP packets can accumulate, and be read in a single call. As an additional benefit, you do not have to re-register via ISockPort_Readable() unless the incoming traffic is really slow.

Timer implementation pseudocode:

myDownloadFunction()
{
    ISockPort_Readable(myBetterCallback);
}

myBetterCallback()
{
    if (AEE_NET_WOULDBLOCK != ISockPort_Read())
    {
        // got some data!  Wait 10ms and try again
        IShell_SetTimer(10, myBetterCallback);
    }
    else
    {
        // oops, no more data. re-register ourselves.
        ISockPort_Readable(myBetterCallback);
    }
}

The difference in usage between these approaches can be visualized in the table below. Please note that the 10 ms timer is a heuristic value. The optimal value may vary for different targets, networks, and expected throughput.