在字节数组读取器/生成器中读取和写入位和位块

时间:2020-06-08 06:21:49

标签: java optimization

我正在寻找一种(算法上)优化的方法,以通过某种形式的字节缓冲区读写不同长度的二进制数据。我需要能够从中创建一个byte数组。理想情况下,此对象可以重用(在单线程环境中)。这些位始终从左到右读取/写入,并且生成的位序列(因此生成的byte数组)的长度是变化的(结尾可以填充零,这是没有问题的)。我需要能够一次在1到3位之间进行读/写操作,最好是从shortbyteint之类的原始数值中进行读取/写入...但是,我最初并不当开始填充数组时,我知道数组的大小。这取决于要转换的对象。因此,我实际上不能使用ByteBuffer,它需要分配一个特定的长度(如本问题/答案中的建议:ByteBuffer and Byte Array)。

读取位时,我可以根据最后读取的位来确定下一个块必须多长时间,因此可以读取特定数量的位。创建的字节数组的末尾应填充零,因此字节数组中最左边的位始终是写入的第一位,最右边的位是最后写入的位,或者是最后写入后的最后填充零。填满最后一个字节。

背景

我正在研究一种算法,该算法需要以很高的频率构造-以后读取-二进制数据。我将此数据存储为byte数组,并根据它们构造String,因此我可以将它们用作各种映射中的键(我使用具有1:1映射的字符集,因此我不在转换过程中会丢失信息)。由于缺乏更好的主意,我使用BigInteger作为缓冲区,并通过将BigInteger转换为byte[]来构造字节数组。示例代码:

public void writeByteArray() {
    // Needs to be 1, so I have a reliable initialization bit, so that if i insert a lot of leading zeros, they are not cut.
    BigInteger buffer = BigInteger.ONE;

    buffer = buffer.shiftLeft(somethingBitLength);
    buffer = buffer.add(BigInteger.valueOf(something));

    buffer = buffer.shiftLeft(somethingElseBitLength);
    buffer = buffer.add(BigInteger.valueOf(somethingElse));
    ...
}

这会生成许多对象,这些对象会立即再次从范围中删除,并且不会转义创建它们的方法上下文。 但是我相信编译器无法识别,大多数短暂的BigIntegers都没有转义,因此在弹出栈后不会立即销毁它们。一旦我的算法运行了几秒钟,我就会运行剧烈的垃圾收集器,这会增加长度。尽管这部分归因于算法通常抛出的大量对象,但GC运行的主要触发因素似乎是这种方法,而第二种方法则以相反的方式读取二进制数据。

我正在寻找什么(针对API)

public static final ByteBuilder BYTES = new ByteBuilder();

...

public byte[] write() {
    BYTES.reset();

    BYTES.append(0b0_101, 3); // arguments: (bits, length)
    BYTES.append(something, somethingLength);
    ...

    return BYTES.toArray(); // generates the minimum length array to wrap the buffered bits.
}

public void read(byte[] bytes) {
    BYTES.load(bytes);

    byte bits = BYTES.next(3) // argument: length. expected: right-aligned bits ('0000_0101', if '101' was read)
    bits = BYTES.next(somethingLength)
    ...

}

从理论上讲,我可以编写这样的class,但是我怀疑这样一个普遍相关的问题已经解决,或者有一些库比我的{{1 }}。

0 个答案:

没有答案
相关问题