Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / October 2007

Tip: Looking for answers? Try searching our database.

Efficiency of stuffing & reconstituting primitives in  a byte[]

Thread view: 
Qu0ll - 04 Oct 2007 13:36 GMT
I am stuffing a byte[] with byte, short and int values and then
reconstituting them elsewhere.  Everything works fine but I am concerned
that I am not doing it as efficiently as possible.

The code to stuff a short named x into the byte[] buffer (high byte first)
looks like this:

buffer[index++] = (byte)(((short)x & 0xFF00) >> 8);
buffer[index++] = (byte)( (short)x & 0x00FF);

The code to reconstitute the short looks like this:

byte a = buffer[index++];
byte b = buffer[index++];
short as = a;
short bs = b < 0 ? (short)((b & 0x7F) + 128) : b;
x = (short)((as << 8) | bs);

Is this the most efficient way of doing this?  I find it annoying that bytes
are signed.  I am also concerned that it may not work for all short values.

Signature

And loving it,

-Q
_________________________________________________
Qu0llSixFour@gmail.com
(Replace the "SixFour" with numbers to email me)

Eric Sosman - 04 Oct 2007 14:19 GMT
> I am stuffing a byte[] with byte, short and int values and then
> reconstituting them elsewhere.  Everything works fine but I am concerned
[quoted text clipped - 5 lines]
> buffer[index++] = (byte)(((short)x & 0xFF00) >> 8);
> buffer[index++] = (byte)( (short)x & 0x00FF);

    The (short) casts are unnecessary unless `x' is a float
or a double.  Also, you can get rid of the masks and just
rely on the (byte) casts:

    buffer[index++] = (byte)(x >> 8);
    buffer[index++] = (byte)x;

... but you'll probably need to do this to quite a large
number of values before you see a measurable speed change.

> The code to reconstitute the short looks like this:
>
[quoted text clipped - 3 lines]
> short bs = b < 0 ? (short)((b & 0x7F) + 128) : b;
> x = (short)((as << 8) | bs);

    You're working too hard.  Try

    short x = (short)(buffer[index++] << 8);
    x += buffer[index++] & 0xFF;

You could even pack all of this into one statement like

    short x = (short)((buffer[index++] << 8)
                     + (buffer[index++] & 0xFF));

... but this is cringe-inducing to old C programmers
like me.  (Even though javac knows how to organize the
side-effects, there's no point in giving the maintenance
programmer a chance to make a "harmless" rearrangement.)

> Is this the most efficient way of doing this?

    Maybe, maybe not, and maybe the answer is different on
different systems.  How much will you suffer if it turns
out to be only the second- or third-most efficient?

> I find it annoying that
> bytes are signed.

    So do I.  I also find it annoying that mosquitoes bite,
but I learn to get along anyhow.

> I am also concerned that it may not work for all
> short values.

    As far as I can tell, both the originals and the rewrites
should work for all values.  But since there are only 65536
short values, you could easily write a little test program
to pack and unpack all of them and report any discrepancies.

Signature

Eric Sosman
esosman@ieee-dot-org.invalid

Patricia Shanahan - 04 Oct 2007 14:39 GMT
...
>> byte a = buffer[index++];
>> byte b = buffer[index++];
[quoted text clipped - 6 lines]
>     short x = (short)(buffer[index++] << 8);
>     x += buffer[index++] & 0xFF;
...
>> Is this the most efficient way of doing this?
>
>     Maybe, maybe not, and maybe the answer is different on
> different systems.  How much will you suffer if it turns
> out to be only the second- or third-most efficient?

There is a risk that the conditional branch version will be slow on deep
pipeline processors for mixed sign data. Each conditional branch that is
not correctly predicted causes a pipeline flush, and subsequent delay
while the correct code works its way though the pipeline.

This seems to me to be a case where the simpler, cleaner code is also
likely to be the more efficient, if there is any difference.

Patricia
Qu0ll - 04 Oct 2007 15:18 GMT
Thank you Eric for your very useful reply.  Comments inline...

> The (short) casts are unnecessary unless `x' is a float
> or a double.  Also, you can get rid of the masks and just
[quoted text clipped - 5 lines]
> ... but you'll probably need to do this to quite a large
> number of values before you see a measurable speed change.

Yes, I see now the unnecessary nature of the (short) casts and masks.  It's
much simpler and easier to maintain this way and makes the task of stuffing
int values easy too.

>     You're working too hard.  Try
>
> short x = (short)(buffer[index++] << 8);
> x += buffer[index++] & 0xFF;

This will do nicely.  I need to do some processing between accesses to the
buffer so this works better for me than the more concise solution you also
suggested.

>     Maybe, maybe not, and maybe the answer is different on
> different systems.  How much will you suffer if it turns
> out to be only the second- or third-most efficient?

It doesn't really matter whether it's an order of magnitude more efficient
or not.  What matters is that it's simpler and that I have learned something
in the process.

>     As far as I can tell, both the originals and the rewrites
> should work for all values.  But since there are only 65536
> short values, you could easily write a little test program
> to pack and unpack all of them and report any discrepancies.

While I haven't run this exact test, I have run the application with a vast
selection of values and it has proven to be 100% reliable.

Thanks again!

Signature

And loving it,

-Q
_________________________________________________
Qu0llSixFour@gmail.com
(Replace the "SixFour" with numbers to email me)

Daniel Pitts - 04 Oct 2007 15:15 GMT
> I am stuffing a byte[] with byte, short and int values and then
> reconstituting them elsewhere.  Everything works fine but I am concerned
[quoted text clipped - 17 lines]
> bytes are signed.  I am also concerned that it may not work for all
> short values.

Have you looked into using a ByteBuffer?
<http://java.sun.com/j2se/1.5.0/docs/api/java/nio/ByteBuffer.html>
It has putInt, putLong, putShort, putChar, putDouble, etc....

You can use ByteBuffer.wrap(bufferArray) too.

HTH.
Signature

Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>

Qu0ll - 04 Oct 2007 19:37 GMT
> Have you looked into using a ByteBuffer?
> <http://java.sun.com/j2se/1.5.0/docs/api/java/nio/ByteBuffer.html>
> It has putInt, putLong, putShort, putChar, putDouble, etc....
>
> You can use ByteBuffer.wrap(bufferArray) too.

Yes, I see now that ByteBuffer does pretty much what I was trying to do but
I am going to stick with the original approach (and Eric's improvements)
because it works, it is as efficient as it can be and all this is happening
inside an applet where I am trying to limit the number of classes being
loaded.

But thanks for the suggestion (also to Nigel for suggesting same).

Signature

And loving it,

-Q
_________________________________________________
Qu0llSixFour@gmail.com
(Replace the "SixFour" with numbers to email me)

Nigel Wade - 04 Oct 2007 16:58 GMT
> I am stuffing a byte[] with byte, short and int values and then
> reconstituting them elsewhere.  Everything works fine but I am concerned
[quoted text clipped - 16 lines]
> Is this the most efficient way of doing this?  I find it annoying that bytes
> are signed.  I am also concerned that it may not work for all short values.

Have you considered using ByteBuffer? It is designed to do exactly this kind of
thing. Whether it is more efficient is another matter entirely, but it ought to
be simpler and your intention should be more transparent.

Signature

Nigel Wade, System Administrator, Space Plasma Physics Group,
           University of Leicester, Leicester, LE1 7RH, UK
E-mail :    nmw@ion.le.ac.uk
Phone :     +44 (0)116 2523548, Fax : +44 (0)116 2523555

Roedy Green - 05 Oct 2007 02:45 GMT
>I am stuffing a byte[] with byte, short and int values and then
>reconstituting them elsewhere.  Everything works fine but I am concerned
>that I am not doing it as efficiently as possible.

You can use a DataOutputStream to a ByteArrayStream.  Sun is going to
write pretty good code.  You can also peek at how Sun does it by
looking up the code in src.zip or letting your IDE find it for you.

I have similar code in LEDataStream doing the same thing for little
endian binary data.

See http://mindprod.com/products.html#LEDATASTREAM
Signature

Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com

Greg R. Broderick - 05 Oct 2007 21:54 GMT
> I am stuffing a byte[] with byte, short and int values and then
> reconstituting them elsewhere.  Everything works fine but I am concerned
> that I am not doing it as efficiently as possible.

Efficiency is in the eyes of the beholder - the code you've written is very
efficient in terms of economy of memory usage, but fails to be efficient when
the code needs to be maintained, as it is relatively difficult to deduce the
purpose of stuffing these three values into one.  This loss of efficiency may
end up costing you more in the long run - what happens when a junior coder is
tasked with adding a fourth value into the composed collection of values.

If your purpose is to return three values as one from a method call, then I
would recommend that you create a small private inner class that contains
each of the three individual values that you need to return as instance
fields, and that you return an object of this class instead of performing
these gymnastics.

Cheers!
GRB

Signature

---------------------------------------------------------------------
Greg R. Broderick                  usenet200709@blackholio.dyndns.org

A. Top posters.
Q. What is the most annoying thing on Usenet?
---------------------------------------------------------------------



Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.