性能字节[]到通用

Ria*_*ers 3 c# performance low-level-api

我需要制作一个byte [] - > T扩展方法,需要它快速(不需要它很漂亮)

在绝对性能关键环境中,此功能将在很短的时间内被称为100次100次.

我们目前正在优化"滴答"级别,每个刻度转换为在callstack中高出几毫秒,因此需要原始速度而不是可维护性(不是我喜欢设计软件,但其背后的推理超出了范围) .

考虑下面的代码,它是干净和可维护的,但它相对较慢(可能是由于装箱和拆箱),这可以优化为更快?

public static T ConvertTo<T>(this byte[] bytes, int offset = 0)
{
    var type = typeof(T);
    if (type == typeof(sbyte)) return bytes[offset].As<T>();
    if (type == typeof(byte)) return bytes[offset].As<T>();
    if (type == typeof(short)) return BitConverter.ToInt16(bytes, offset).As<T>();
    if (type == typeof(ushort)) return BitConverter.ToUInt32(bytes, offset).As<T>();
    if (type == typeof(int)) return BitConverter.ToInt32(bytes, offset).As<T>();
    if (type == typeof(uint)) return BitConverter.ToUInt32(bytes, offset).As<T>();
    if (type == typeof(long)) return BitConverter.ToInt64(bytes, offset).As<T>();
    if (type == typeof(ulong)) return BitConverter.ToUInt64(bytes, offset).As<T>();

    throw new NotImplementedException();
}

public static T As<T>(this object o)
{
    return (T)o;
}
Run Code Online (Sandbox Code Playgroud)

exy*_*xyi 6

我也需要这个,我发现使用指针和不安全的代码可以更快地完成对这些原始类型的转换.喜欢:

public unsafe int ToInt(byte[] bytes, int offset)
{
    fixed(byte* ptr = bytes)
    {
         return *(int*)(ptr + offset);
    }
}
Run Code Online (Sandbox Code Playgroud)

但遗憾的是C#不支持泛型指针类型,因此我不得不在IL中编写这段代码,而不关心泛型约束:

.method public hidebysig static !!T  Read<T>(void* ptr) cil managed
{
    .maxstack  8
    nop         
    ldarg.0     
    ldobj !!T
    ret 
}
Run Code Online (Sandbox Code Playgroud)

它不漂亮,但它似乎适用于我的情况.使用此方法时要小心 - 您可以将任何类型作为参数传递,但我不知道它会做什么.

您可以在github上找到整个il文件 或下载已编译的程序集https://github.com/exyi/RaptorDB-Document/blob/master/GenericPointerHelpers/GenericPointerHelpers.dll?raw=true我在那里有更多帮助程序.

编辑:我忘了写如何使用这种方法.假设你GenericPointerHelper像我一样在类中编译了方法,你可以实现ConvertTo类似于我的方法ToInt:

public unsafe T ConvertTo<T>(byte[] bytes, int offset)
    where T: struct // not needed to work, just to eliminate some errors
{
    fixed(byte* ptr = bytes)
    {
         return GenericPointerHelper.Read<T>(ptr + offset);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 非常有趣,将不得不深入研究这个,谢谢你,我会在几天内将其标记为答案,除非有更实际的答案 (2认同)