开发者

Replacement for Java ByteBuffer in this case?

Working with the Android Profiler tool, I've discovered that I'm using lots of ByteBuffers in a performance critical area of my code. I've worked on optimizing as much as possible of the largest performance hits (haven't been forced to go to stuff like loop optimization yet) and the ByteBuffer code looks like it could easily be replaced with another/a better solution.

开发者_StackOverflow

The Problem: Getting an int from 4 consecutive bytes located in the ByteBuffer stream, which could be of any length, currently done (seen below, specifically //<<< parts) with a temp ByteBuffer and grabbing needed bytes to form an int. Is there any simpler process?

private int peekStreamData(ByteBuffer stream, int count) {
    int data = 0;
    int stream_field = streamField;
    int stream_field_bit_index = streamFieldBitIndex;
    byte[] streamArr = stream.array();
    ByteBuffer bb = ByteBuffer.allocate(4);
    while (count > (32 - stream_field_bit_index) && streamIndex < (imageStream.capacity() >> 2)) {
        data = (data << (32 - stream_field_bit_index)) | ( stream_field >>> stream_field_bit_index);
        count -= 32 - stream_field_bit_index;

        bb.put(0,streamArr[streamIndex * 4 + 3]);  //<<<
        bb.put(1,streamArr[streamIndex * 4 + 2]);  //<<<
        bb.put(2,streamArr[streamIndex * 4 + 1]);  //<<<
        bb.put(3,streamArr[streamIndex * 4 + 0]);  //<<<
        stream_field = bb.getInt();                //<<<        
        stream_field_bit_index = 0;
    }
    if (count > 0)
        data = (data << count) | (stream_field >>> (32 - count));
    return data;//data;
}

Please feel free to point out any mistakes. I've never worked with ByteBuffers until quite recently and would love to learn.


These lines

    bb.put(0,streamArr[streamIndex * 4 + 3]);  //<<<
    bb.put(1,streamArr[streamIndex * 4 + 2]);  //<<<
    bb.put(2,streamArr[streamIndex * 4 + 1]);  //<<<
    bb.put(3,streamArr[streamIndex * 4 + 0]);  //<<<
    stream_field = bb.getInt();                //<<<

can be replaced with the following with a second ByteBuffer.

    stream_field = stream.getInt(streamIndex * 4);

I suspect much of the other code can be simplified, but its not clear to me what it does or why there is even a loop to do it.


Have you tried:

stream_field = (streamArr[streamIndex * 4 + 0] & 0xFF) | ((streamArr[streamIndex * 4 + 1] & 0xFF) << 8) | ((streamArr[streamIndex * 4 + 2] & 0xFF) << 16) | ((streamArr[streamIndex * 4 + 3] & 0xFF) << 24);

or:

stream_field = ((streamArr[streamIndex * 4 + 0] & 0xFF) << 24) | ((streamArr[streamIndex * 4 + 1] & 0xFF) << 16) | ((streamArr[streamIndex * 4 + 2] & 0xFF) << 8) | (streamArr[streamIndex * 4 + 3] & 0xFF);

depending on endiannes.

EDIT: In Java byte is signed, so they need masking. Corrected.


You can just combine the four bytes into an int instead of using a temporary ByteBuffer. By default, the four bytes are in big-endian byte order. Also, you don't have to calculate "streamIndex * 4" four times in a row.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜