-
Notifications
You must be signed in to change notification settings - Fork 321
Optimize unpackBinary #104
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
9319d52
60f3a13
b71b05a
c963037
952996e
e65da3e
ed0f7cc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| package org.msgpack.core.buffer; | ||
|
|
||
| import java.io.IOException; | ||
| import java.nio.ByteBuffer; | ||
| import static org.msgpack.core.Preconditions.*; | ||
|
|
||
| /** | ||
| * {@link MessageBufferInput} adapter for {@link java.nio.ByteBuffer} | ||
| */ | ||
| public class ByteBufferInput implements MessageBufferInput { | ||
|
|
||
| private final ByteBuffer input; | ||
| private boolean isRead = false; | ||
|
|
||
| public ByteBufferInput(ByteBuffer input) { | ||
| this.input = checkNotNull(input, "input ByteBuffer is null"); | ||
| } | ||
|
|
||
|
|
||
| @Override | ||
| public MessageBuffer next() throws IOException { | ||
| if(isRead) | ||
| return null; | ||
|
|
||
| isRead = true; | ||
| return MessageBuffer.wrap(input); | ||
| } | ||
|
|
||
|
|
||
| @Override | ||
| public void close() throws IOException { | ||
| // Nothing to do | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,10 @@ | ||
| package org.msgpack.core.buffer; | ||
|
|
||
| import java.io.ByteArrayInputStream; | ||
| import java.io.FileInputStream; | ||
| import java.io.IOException; | ||
| import java.io.InputStream; | ||
| import java.lang.reflect.Field; | ||
|
|
||
| import static org.msgpack.core.Preconditions.checkNotNull; | ||
|
|
||
|
|
@@ -10,29 +13,82 @@ | |
| */ | ||
| public class InputStreamBufferInput implements MessageBufferInput { | ||
|
|
||
| private static Field bufField; | ||
| private static Field bufPosField; | ||
| private static Field bufCountField; | ||
|
|
||
| private static Field getField(String name) { | ||
| Field f = null; | ||
| try { | ||
| f = ByteArrayInputStream.class.getDeclaredField(name); | ||
| f.setAccessible(true); | ||
| } | ||
| catch(Exception e) { | ||
| e.printStackTrace(); | ||
| } | ||
| return f; | ||
| } | ||
|
|
||
| static { | ||
| bufField = getField("buf"); | ||
| bufPosField = getField("pos"); | ||
| bufCountField = getField("count"); | ||
| } | ||
|
|
||
| private final InputStream in; | ||
| private byte[] buffer = new byte[8192]; | ||
| private final int bufferSize; | ||
| private boolean reachedEOF = false; | ||
|
|
||
| public static MessageBufferInput newBufferInput(InputStream in) { | ||
| checkNotNull(in, "InputStream is null"); | ||
| if(in.getClass() == ByteArrayInputStream.class) { | ||
| ByteArrayInputStream b = (ByteArrayInputStream) in; | ||
| try { | ||
| // Extract a raw byte array from the ByteArrayInputStream | ||
| byte[] buf = (byte[]) bufField.get(b); | ||
| int pos = (Integer) bufPosField.get(b); | ||
| int length = (Integer) bufCountField.get(b); | ||
| return new ArrayBufferInput(buf, pos, length); | ||
| } | ||
| catch(Exception e) { | ||
| // Failed to retrieve the raw byte array | ||
| } | ||
| } else if (in instanceof FileInputStream) { | ||
| return new ChannelBufferInput(((FileInputStream) in).getChannel()); | ||
| } | ||
|
|
||
| return new InputStreamBufferInput(in); | ||
| } | ||
|
|
||
| public InputStreamBufferInput(InputStream in) { | ||
| this(in, 8192); | ||
| } | ||
|
|
||
| public InputStreamBufferInput(InputStream in, int bufferSize) { | ||
| this.in = checkNotNull(in, "input is null"); | ||
| this.bufferSize = bufferSize; | ||
| } | ||
|
|
||
| @Override | ||
| public MessageBuffer next() throws IOException { | ||
| // Manage the allocated buffers | ||
| MessageBuffer m = MessageBuffer.newBuffer(buffer.length); | ||
| if(reachedEOF) | ||
| return null; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good idea. Thanks.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I tested to read InputStream after it returns -1. Instead of returning -1, it blocks. I used GZipInputStream(ByteArrayInputStream) as an InputStream. So we should use |
||
|
|
||
| // TODO reduce the number of memory copy | ||
| byte[] buffer = null; | ||
| int cursor = 0; | ||
| while(cursor < buffer.length) { | ||
| int readLen = in.read(buffer, cursor, buffer.length - cursor); | ||
| while(!reachedEOF && cursor < bufferSize) { | ||
| if(buffer == null) | ||
| buffer = new byte[bufferSize]; | ||
|
|
||
| int readLen = in.read(buffer, cursor, bufferSize - cursor); | ||
| if(readLen == -1) { | ||
| reachedEOF = true; | ||
| break; | ||
| } | ||
| cursor += readLen; | ||
| } | ||
| m.putBytes(0, buffer, 0, cursor); | ||
| return m; | ||
|
|
||
| return buffer == null ? null : MessageBuffer.wrap(buffer).slice(0, cursor); | ||
| } | ||
|
|
||
| @Override | ||
|
|
@@ -41,7 +97,7 @@ public void close() throws IOException { | |
| in.close(); | ||
| } | ||
| finally { | ||
| buffer = null; | ||
|
|
||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -114,10 +114,10 @@ public class MessageBuffer { | |
| * Reference is used to hold a reference to an object that holds the underlying memory so that it cannot be | ||
| * released by the garbage collector. | ||
| */ | ||
| private final ByteBuffer reference; | ||
| protected final ByteBuffer reference; | ||
|
|
||
| // TODO life-time managment of this buffer | ||
| private AtomicInteger referenceCounter; | ||
| //private AtomicInteger referenceCounter; | ||
|
|
||
|
|
||
| static MessageBuffer newOffHeapBuffer(int length) { | ||
|
|
@@ -243,7 +243,7 @@ else if(bb.hasArray()) { | |
| this.reference = null; | ||
| } | ||
|
|
||
| private MessageBuffer(Object base, long address, int length, ByteBuffer reference) { | ||
| protected MessageBuffer(Object base, long address, int length, ByteBuffer reference) { | ||
| this.base = base; | ||
| this.address = address; | ||
| this.size = length; | ||
|
|
@@ -259,7 +259,12 @@ private MessageBuffer(Object base, long address, int length, ByteBuffer referenc | |
|
|
||
| public MessageBuffer slice(int offset, int length) { | ||
| // TODO ensure deleting this slice does not collapse this MessageBuffer | ||
| return new MessageBuffer(base, address + offset, length, reference); | ||
| if(offset == 0 && length == size()) | ||
| return this; | ||
| else { | ||
| checkArgument(offset + length <= size()); | ||
| return new MessageBuffer(base, address + offset, length, reference); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about checking here if the sum of
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK. If that test fails this code should throw IllegalArgumentException. |
||
| } | ||
| } | ||
|
|
||
| public byte getByte(int index) { | ||
|
|
@@ -388,6 +393,17 @@ public ByteBuffer toByteBuffer(int index, int length) { | |
| } | ||
| } | ||
|
|
||
| public ByteBuffer toByteBuffer() { | ||
| return toByteBuffer(0, size()); | ||
| } | ||
|
|
||
| public byte[] toByteArray() { | ||
| byte[] b = new byte[size()]; | ||
| unsafe.copyMemory(base, address, b, ARRAY_BYTE_BASE_OFFSET, size()); | ||
| return b; | ||
| } | ||
|
|
||
|
|
||
| public void relocate(int offset, int length, int dst) { | ||
| unsafe.copyMemory(base, address + offset, base, address+dst, length); | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
very good optimization 👍