优化数据流上 ReadInt 的位读取器



谁能帮我优化这段代码? 它目前是一个很大的瓶颈,因为它经常被调用。 即使速度提高 25% 也会显着。

public int ReadInt(int length)
{
    if (Position + length > Length)
        throw new BitBufferException("Not enough bits remaining.");
    int result = 0;
    while (length > 0)
    {
        int off = Position & 7;
        int count = 8 - off;
        if (count > length)
            count = length;
        int mask = (1 << count) - 1;
        int bits = (Data[Position >> 3] >> off);
        result |= (bits & mask) << (length - count);
        length -= count;
        Position += count;
    }
    return result;
}

最好的答案是最快的解决方案。使用点跟踪完成的基准测试。 目前,此代码块约占总CPU时间的15%。 数字最低,最佳答案。

编辑:示例用法:

          public class Auth : Packet
          {
            int Field0;
            int ProtocolHash;
            int Field1;
            public override void Parse(buffer)
            {
            Field0 = buffer.ReadInt(9);
            ProtocolHash = buffer.ReadInt(32);
            Field1 = buffer.ReadInt(8);
            }
          }

数据大小是可变的,但在大多数情况下为 512 字节;

使用指针和unsafe上下文怎么样?你没有说你的输入数据、方法上下文等,所以我试图自己扣除所有这些。

public class BitTest
{
    private int[] _data;
    public BitTest(int[] data)
    {
        Length = data.Length * 4 * 8;
        // +2, because we use byte* and long* later
        // and don't want to read outside the array memory
        _data = new int[data.Length + 2];
        Array.Copy(data, _data, data.Length);
    }
    public int Position { get; private set; }
    public int Length { get; private set; }

ReadInt方法。希望评论能对解决方案有所了解:

    public unsafe int ReadInt(int length)
    {
        if (Position + length > Length)
            throw new ArgumentException("Not enough bits remaining.");
        // method returns int, so getting more then 32 bits is pointless
        if (length > 4 * 8)
            throw new ArgumentException();
        // 
        int bytePosition = Position / 8;
        int bitPosition = Position % 8;
        Position += length;
        // get int* on array to start with
        fixed (int* array = _data)
        {
            // change pointer to byte*
            byte* bt = (byte*)array;
            // skip already read bytes and change pointer type to long*
            long* ptr = (long*)(bt + bytePosition);
            // read value from current pointer position
            long value = *ptr;
            // take only necessary bits
            value &= (1L << (length + bitPosition)) - 1;
            value >>= bitPosition;
            // cast value to int before returning
            return (int)value;
        }
    }
}

我没有测试该方法,但敢打赌它比你的方法快得多。

我的简单测试代码:

var data = new[] { 1 | (1 << 8 + 1) | (1 << 16 + 2) | (1 << 24 + 3) };
var test = new BitTest(data);
var bytes = Enumerable.Range(0, 4)
                      .Select(x => test.ReadInt(8))
                      .ToArray();

bytes包含{ 1, 2, 4, 8},正如预期的那样。

我不知道

这是否会给你带来显着的改进,但它应该给你一些数字。

与其在循环

中创建新的 int 变量(这需要时间来创建),不如在进入循环之前保留这些变量。

public int ReadInt(int length)
{
if (Position + length > Length)
    throw new BitBufferException("Not enough bits remaining.");
int result = 0;
int off = 0;
int count = 0;
int mask = 0;
int bits = 0
while (length > 0)
{
    off = Position & 7;
    count  = 8 - off;
    if (count > length)
        count = length;
    mask = (1 << count) - 1;
    bits = (Data[Position >> 3] >> off);
    result |= (bits & mask) << (length - count);
    length -= count;
    Position += count;
}
return result;
}

希望这能提高你的表现一点

相关内容

  • 没有找到相关文章

最新更新