Buffer the slip packet before sending.

On Mac OS X, sending the slip packet byte by byte results in an abysmal
performance. The first byte takes up to 160ms to send, and each next
byte approximately 250ms. The packet to request a data block is
typically 7 bytes large, and therefore takes about 1660ms to send.
Because a dive is transmitted as multiple smaller packets (typically
144 bytes without protocol overhead), downloading a single dive can
easily take several seconds.

However, when sending the entire slip packet at once, the time remains
roughly identical to sending just the first byte. The result is that
the time for sending a packet reduces significantly, proportional to
the length of the packet.

Under the hood, the slip packet is now internally buffered, and the
buffer is send only when the entire packet is complete, or whenever the
buffer gets full. But in practice, the buffer is large enough to always
store an entire packet.

In the original bug report, downloading 57 dives took about 40 minutes.
After applying the patch, that time reduced to only 5 minutes!
This commit is contained in:
Jef Driesen 2013-09-20 21:58:50 +02:00
parent 6f7495dd3e
commit 8e0355c354

View File

@ -148,6 +148,8 @@ shearwater_common_slip_write (shearwater_common_device_t *device, const unsigned
const unsigned char end[] = {END};
const unsigned char esc_end[] = {ESC, ESC_END};
const unsigned char esc_esc[] = {ESC, ESC_ESC};
unsigned char buffer[32];
unsigned int nbytes = 0;
#if 0
// Send an initial END character to flush out any data that may have
@ -179,15 +181,28 @@ shearwater_common_slip_write (shearwater_common_device_t *device, const unsigned
break;
}
n = serial_write (device->port, seq, len);
if (n != len) {
return EXITCODE(n);
// Flush the buffer if necessary.
if (nbytes + len + sizeof(end) > sizeof(buffer)) {
n = serial_write (device->port, buffer, nbytes);
if (n != nbytes) {
return EXITCODE(n);
}
nbytes = 0;
}
// Append the escaped character.
memcpy(buffer + nbytes, seq, len);
nbytes += len;
}
// Send the END character to indicate the end of the packet.
n = serial_write (device->port, end, sizeof (end));
if (n != sizeof (end)) {
// Append the END character to indicate the end of the packet.
memcpy(buffer + nbytes, end, sizeof(end));
nbytes += sizeof(end);
// Flush the buffer.
n = serial_write (device->port, buffer, nbytes);
if (n != nbytes) {
return EXITCODE(n);
}