86: use nio direct buffers where possible to reduce byte copying

Reviewed-by: jfdenise, kinsleyw
This commit is contained in:
akhil 2013-11-22 15:38:26 -08:00
parent 3dccf4035d
commit 91c54e164d
5 changed files with 45 additions and 21 deletions

View File

@ -55,7 +55,7 @@ public final class Buffer {
}
public Buffer(final int size) {
byteBuffer = ByteBuffer.allocate(size);
byteBuffer = ByteBuffer.allocateDirect(size);
}
public Buffer(final Double[] numbers) {
@ -135,10 +135,6 @@ public final class Buffer {
return this;
}
public Buffer asReadOnlyBuffer() {
return new Buffer(byteBuffer.asReadOnlyBuffer().array());
}
public Buffer slice() {
return new Buffer(byteBuffer.slice());
}
@ -148,7 +144,15 @@ public final class Buffer {
}
public byte[] array() {
return byteBuffer.array();
if (byteBuffer.hasArray()) {
return byteBuffer.array();
} else {
final ByteBuffer dup = byteBuffer.duplicate();
final byte[] data = new byte[dup.capacity()];
dup.clear();
dup.get(data);
return data;
}
}
public ByteBuffer underlying() {
@ -174,11 +178,11 @@ public final class Buffer {
}
public String toStringContent() {
return new String(byteBuffer.array());
return new String(array());
}
public String toStringContent(final Charset charset) {
return new String(byteBuffer.array(), charset);
return new String(array(), charset);
}
public String toStringContent(final Charset charset, final int position, final int limit) {
@ -271,21 +275,42 @@ public final class Buffer {
public int copy(final Buffer targetBuffer, final int targetStart, final int sourceStart, final int sourceEnd) {
final int len = Math.min(sourceEnd - sourceStart, targetBuffer.byteBuffer.capacity());
System.arraycopy(byteBuffer.array(), sourceStart, targetBuffer.byteBuffer.array(), targetStart, len);
if (byteBuffer.hasArray() && targetBuffer.byteBuffer.hasArray()) {
System.arraycopy(byteBuffer.array(), sourceStart, targetBuffer.byteBuffer.array(), targetStart, len);
} else if (targetBuffer.byteBuffer.hasArray()) {
System.arraycopy(array(), sourceStart, targetBuffer.byteBuffer.array(), targetStart, len);
} else {
final int pos = targetBuffer.byteBuffer.position();
try {
targetBuffer.byteBuffer.position(targetStart);
targetBuffer.byteBuffer.put(array(), sourceStart, len);
} finally {
targetBuffer.byteBuffer.position(pos);
}
}
return len;
}
public String toString(final String encoding, final int start, final int length)
throws UnsupportedEncodingException {
return Buffer.fromBytes(Arrays.copyOfRange(byteBuffer.array(), start, start + length), encoding);
return Buffer.fromBytes(Arrays.copyOfRange(array(), start, start + length), encoding);
}
public Buffer slice(final int position, final int end) {
return new Buffer(Arrays.copyOfRange(byteBuffer.array(), position, end));
return new Buffer(Arrays.copyOfRange(array(), position, end));
}
public void fill(final Double value, final int start, final int end) {
Arrays.fill(byteBuffer.array(), start, end, value.byteValue());
if (byteBuffer.hasArray()) {
Arrays.fill(byteBuffer.array(), start, end, value.byteValue());
} else {
final byte[] data = new byte[end - start];
Arrays.fill(data, value.byteValue());
final ByteBuffer dup = byteBuffer.duplicate();
dup.clear();
dup.position(start);
dup.put(data, 0, data.length);
}
}
public int readInt8(final int off) {
@ -549,9 +574,8 @@ public final class Buffer {
sb.append("<");
sb.append(slow ? "Slow" : "");
sb.append("Buffer ");
final byte[] array = byteBuffer.array();
for (int i = 0; i < byteBuffer.limit(); i++) {
sb.append(String.format("%02x", array[i]));
sb.append(String.format("%02x", byteBuffer.get(i)));
final int nexti = i + 1;
if (nexti < maxBytes) {
if (nexti < byteBuffer.limit()) {

View File

@ -62,7 +62,7 @@ public class StringDecoder {
public String write(Buffer buffer) {
// The received buffer can be fully consumed
ByteBuffer buff = ByteBuffer.allocate(buffer.capacity());
buff.put(buffer.array());
buff.put(buffer.underlying());
buff.flip();
ByteBuffer nBuffer = buff;
if (remaining != null) {

View File

@ -200,7 +200,7 @@ final class LoopCallbackHandler implements CallbackHandler {
}
@Override
public void handleFileReadCallback(final FileReadCallback cb, final Object context, final int bytesRead, final byte[] data, final Exception error) {
public void handleFileReadCallback(final FileReadCallback cb, final Object context, final int bytesRead, final ByteBuffer data, final Exception error) {
try {
cb.onRead(context, bytesRead, data, error);
eventLoop.processQueuedEvents();

View File

@ -84,10 +84,10 @@
position = -1;
}
if (typeof callback === 'function') {
return fs.read(fd, buffer._impl.array(), offset, length, position, callback);
return fs.read(fd, buffer._impl.underlying(), offset, length, position, callback);
} else {
try {
return fs.read(fd, buffer._impl.array(), offset, length, position);
return fs.read(fd, buffer._impl.underlying(), offset, length, position);
} catch(e) {
throw newError(e);
}
@ -130,10 +130,10 @@
}
if (typeof callback === 'function') {
var r = fs.write(fd, buffer._impl.array(), offset, length, position, callback);
var r = fs.write(fd, buffer._impl.underlying(), offset, length, position, callback);
} else {
try {
return fs.write(fd, buffer._impl.array(), offset, length, position);
return fs.write(fd, buffer._impl.underlying(), offset, length, position);
} catch(e) {
throw newError(e);
}

View File

@ -201,7 +201,7 @@
var buff = new Buffer(length);
data.copy(buff, 0, start, start + length);
this._got_exception = null;
var nparsed = this._parser.execute(this._settings, buff._impl.toByteBuffer());
var nparsed = this._parser.execute(this._settings, buff._impl.underlying());
if (this._got_exception)
throw this._got_exception;
if (!this._parser.upgrade() && nparsed != length) {