Remove unnecessary byte buffer allocations in the most frequent control stream packets

This commit is contained in:
Cameron Gutman 2014-09-15 01:02:33 -07:00
parent 4377808896
commit 7124963c56

View File

@ -80,7 +80,7 @@ public class ControlStream implements ConnectionStatusListener {
private void sendPacket(NvCtlPacket packet) throws IOException private void sendPacket(NvCtlPacket packet) throws IOException
{ {
out.write(packet.toWire()); packet.write(out);
out.flush(); out.flush();
} }
@ -90,10 +90,9 @@ public class ControlStream implements ConnectionStatusListener {
return new NvCtlResponse(in); return new NvCtlResponse(in);
} }
private void sendLossStats() throws IOException private void sendLossStats(ByteBuffer bb) throws IOException
{ {
ByteBuffer bb = ByteBuffer.allocate(PPAYLEN_LOSS_STATS).order(ByteOrder.LITTLE_ENDIAN); bb.rewind();
bb.putInt(lossCountSinceLastReport); // Packet loss count bb.putInt(lossCountSinceLastReport); // Packet loss count
bb.putInt(LOSS_REPORT_INTERVAL_MS); // Time since last report in milliseconds bb.putInt(LOSS_REPORT_INTERVAL_MS); // Time since last report in milliseconds
bb.putInt(1000); bb.putInt(1000);
@ -148,10 +147,12 @@ public class ControlStream implements ConnectionStatusListener {
lossStatsThread = new Thread() { lossStatsThread = new Thread() {
@Override @Override
public void run() { public void run() {
ByteBuffer bb = ByteBuffer.allocate(PPAYLEN_LOSS_STATS).order(ByteOrder.LITTLE_ENDIAN);
while (!isInterrupted()) while (!isInterrupted())
{ {
try { try {
sendLossStats(); sendLossStats(bb);
lossCountSinceLastReport = 0; lossCountSinceLastReport = 0;
} catch (IOException e) { } catch (IOException e) {
listener.connectionTerminated(e); listener.connectionTerminated(e);
@ -250,39 +251,42 @@ public class ControlStream implements ConnectionStatusListener {
sendAndGetReply(new NvCtlPacket(PTYPE_RESYNC, PPAYLEN_RESYNC, conf.array())); sendAndGetReply(new NvCtlPacket(PTYPE_RESYNC, PPAYLEN_RESYNC, conf.array()));
} }
class NvCtlPacket { static class NvCtlPacket {
public short type; public short type;
public short paylen; public short paylen;
public byte[] payload; public byte[] payload;
private static final ByteBuffer headerBuffer = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN);
public NvCtlPacket(InputStream in) throws IOException public NvCtlPacket(InputStream in) throws IOException
{ {
byte[] header = new byte[4]; // Use the class's static header buffer for parsing the header
synchronized (headerBuffer) {
int offset = 0; int offset = 0;
do byte[] header = headerBuffer.array();
{ do
int bytesRead = in.read(header, offset, header.length - offset); {
if (bytesRead < 0) { int bytesRead = in.read(header, offset, header.length - offset);
break; if (bytesRead < 0) {
break;
}
offset += bytesRead;
} while (offset != header.length);
if (offset != header.length) {
throw new IOException("Socket closed prematurely");
} }
offset += bytesRead;
} while (offset != header.length); headerBuffer.rewind();
type = headerBuffer.getShort();
if (offset != header.length) { paylen = headerBuffer.getShort();
throw new IOException("Socket closed prematurely");
} }
ByteBuffer bb = ByteBuffer.wrap(header).order(ByteOrder.LITTLE_ENDIAN);
type = bb.getShort();
paylen = bb.getShort();
if (paylen != 0) if (paylen != 0)
{ {
payload = new byte[paylen]; payload = new byte[paylen];
offset = 0; int offset = 0;
do do
{ {
int bytesRead = in.read(payload, offset, payload.length - offset); int bytesRead = in.read(payload, offset, payload.length - offset);
@ -298,17 +302,22 @@ public class ControlStream implements ConnectionStatusListener {
} }
} }
public NvCtlPacket(byte[] payload) public NvCtlPacket(byte[] packet)
{ {
ByteBuffer bb = ByteBuffer.wrap(payload).order(ByteOrder.LITTLE_ENDIAN); synchronized (headerBuffer) {
headerBuffer.rewind();
headerBuffer.put(packet, 0, 4);
headerBuffer.rewind();
type = headerBuffer.getShort();
paylen = headerBuffer.getShort();
}
type = bb.getShort(); if (paylen != 0)
paylen = bb.getShort();
if (bb.hasRemaining())
{ {
payload = new byte[bb.remaining()]; payload = new byte[paylen];
bb.get(payload); System.arraycopy(packet, 4, payload, 0, paylen);
} }
} }
@ -345,17 +354,17 @@ public class ControlStream implements ConnectionStatusListener {
this.paylen = paylen; this.paylen = paylen;
} }
public byte[] toWire() public void write(OutputStream out) throws IOException
{ {
ByteBuffer bb = ByteBuffer.allocate(4 + (payload != null ? payload.length : 0)).order(ByteOrder.LITTLE_ENDIAN); // Use the class's header buffer to construct the wireform to send
synchronized (headerBuffer) {
headerBuffer.rewind();
headerBuffer.putShort(type);
headerBuffer.putShort(paylen);
out.write(headerBuffer.array());
}
bb.putShort(type); out.write(payload);
bb.putShort(paylen);
if (payload != null)
bb.put(payload);
return bb.array();
} }
} }