问题 Java中将位打包成byte []并将其读回的最有效方法是什么?


我目前使用这两个函数来打包和读取字节数组中的位。想知道是否有人有更好的想法或更快的方法吗?

通过更多优化编辑程序并提出一些计算。目前100mil的Put and Get大约需要12秒而不是16秒。

如果有人正在使用当前代码,请确保传入Put的值是正数,因为它期望无符号数字下降。如果有兴趣,我可以提出签名和未签名的版本。

class BitData
{
    static void Put(byte Data[], final int BitOffset, int NumBits, final int Value)
    {
        final long valLong=(Value&((1L<<NumBits)-1L));
        int posByte=BitOffset>>3;
        int posBit=BitOffset&7;
        int valByte;
        int ModifyBits;

        long lValue;
        int LeftShift;
        ModifyBits=8-posBit;
        if(NumBits<ModifyBits) ModifyBits=NumBits;
        LeftShift=(8-posBit-ModifyBits);
        while(true)
        {
            valByte = Data[posByte];
            if(ModifyBits==8)
            {
                lValue=valLong<<(32-NumBits)>>(24);
                Data[posByte]=(byte)lValue;
            }
            else
            {   
                lValue=valLong<<(32-NumBits)>>(32-ModifyBits)<<LeftShift;
                Data[posByte]=(byte)((valByte & ~(((1<<ModifyBits)-1) << LeftShift)) | lValue);
            }
            NumBits-=ModifyBits;
            if(NumBits==0) break;
            posByte++;          
            ModifyBits=8;
            if(NumBits<ModifyBits) 
            {
                ModifyBits=NumBits;
                LeftShift=(8-ModifyBits);
            }
        }
    }

    static int GetInt(byte Data[], final int BitOffset, int NumBits)
    {       
        int posByte=BitOffset>>3;
        int posBit=BitOffset&7;


        long Value=0;
        int ModifyBits;
        int valByte;
        int LeftShift;
        ModifyBits=8-posBit;
        if(NumBits<ModifyBits) ModifyBits=NumBits;
        LeftShift=(8-posBit-ModifyBits);
        while(true)
        {
            valByte = Data[posByte] & 0xff;
            if(ModifyBits==8) Value+=valByte;
            else Value+=(valByte & ((1<<ModifyBits)-1) << LeftShift) >> LeftShift;              
            NumBits-=ModifyBits;
            if(NumBits==0) break;
            posByte++;
            ModifyBits=8;
            if(NumBits<ModifyBits) 
            {
                ModifyBits=NumBits;
                LeftShift=(8-ModifyBits);
            }
            Value<<=ModifyBits;

        }
        return (int)Value;
    }
}

12592
2017-09-29 23:57


起源

你考虑过使用内置功能吗? java.util.BitSet? - Jim Garrison
是的,先尝试过。它比这种方法慢很多。它是一台服务器,需要每秒打包和解包数百万个数据包,因此需要尽可能快的方式来完成。我已经使用这两个函数做了尽可能多的优化。只是好奇我是否有一个完全不同的路线,我没有想到用Java。 - user972178
是。用C语言编写并使用JNI将其与Java连接。 - Jim Garrison
该程序也需要便携式。我不熟悉JNI。如果我走这条路线,你能告诉我程序是否仍然可以在不同的os服务器上运行吗? - user972178
我对JNI了解不多。由于JNI代码不会执行任何I / O或与操作系统交互,因此我认为差异非常非常小。您可能会使用一个源,但需要为每个OS /硬件组合分配二进制文件。 - Jim Garrison


答案:


一个完全不同的路线是定义所有可能组合的静态表并执行查找而不是每次计算结果。我认为他们是如何在密码学中做到的。 array [i] x 3应该比numBits按位运算快得多。它会占用一些堆。


11
2017-09-30 03:16



将尝试并列出一些部分,看看是否有速度增加。 - user972178
我添加的两个表似乎提高了性能约7-10%。在代码中找不到适合表的任何其他内容。 10%的收益仍然很好。 - user972178
很好,谢谢分享! - mazaneicha