使用BitConverter在C#中快速转换,它可以更快吗?

时间:2011-02-07 16:41:35

标签: c# .net casting bitconverter

在我们的应用程序中,我们有一个非常大的字节数组,我们必须将这些字节转换为不同的类型。目前,我们使用BitConverter.ToXXXX()来实现此目的。我们的重量级人物是ToInt16ToUInt64

对于UInt64,我们的问题是数据流实际上有6个字节的数据来表示一个大整数。由于没有将6字节数据转换为UInt64的本机函数,我们执行:

UInt64 value = BitConverter.ToUInt64() & 0x0000ffffffffffff;

我们对ToInt16的使用更简单,不必做任何操作。

我们在这两项操作中做了很多,我想向SO社区询问是否有更快的方式来进行这些转换。现在,这两个函数消耗了大约20%的整个CPU周期。

4 个答案:

答案 0 :(得分:6)

您是否考虑过直接使用内存指针?我无法保证其性能,但它是C ++ \ C ...

中的常见技巧
        byte[] arr = { 1, 2, 3, 4, 5, 6, 7, 8 ,9,10,11,12,13,14,15,16};

        fixed (byte* a2rr = &arr[0])
        {

            UInt64* uint64ptr = (UInt64*) a2rr;
            Console.WriteLine("The value is {0:X2}", (*uint64ptr & 0x0000FFFFFFFFFFFF));
            uint64ptr = (UInt64*) ((byte*) uint64ptr+6);
            Console.WriteLine("The value is {0:X2}", (*uint64ptr & 0x0000FFFFFFFFFFFF));
        }

您需要在构建设置中使您的程序集“不安全”,并标记您不安全的方法。通过这种方法,你也与小端有关。

答案 1 :(得分:4)

您可以使用System.Buffer类将整个数组复制到另一个不同类型的数组作为快速'block copy'操作:

  

BlockCopy方法使用偏移量访问内存中的src参数数组中的字节,而不是编程构造,如索引或上下数组边界。

数组类型必须是“原始”类型,它们必须对齐,并且复制操作对字节序敏感。在你的6字节整数的情况下,它不能与任何.NET的'原始'类型对齐,除非你可以获得每六个填充两个字节的源数组,然后将其与Int64对齐。但是这种方法适用于Int16的数组,这可能会加快你的一些操作。

答案 2 :(得分:2)

为什么不:

UInt16 valLow = BitConverter.ToUInt16();
UInt64 valHigh = (UInt64)BitConverter.ToUInt32();
UInt64 Value = (valHigh << 16) | valLow;

您可以将其作为单个语句,尽管JIT编译器可能会自动为您执行此操作。

这将阻止你阅读最后丢弃的额外两个字节。

如果这不会减少CPU,那么您可能想要编写自己的转换器,直接从缓冲区读取字节。您可以使用数组索引,或者,如果您认为有必要,可以使用带有指针的不安全代码。

请注意,正如评论者指出的那样,如果你使用这些建议中的任何一个,那么要么限制为特定的“endian-ness”,要么你必须编写代码来检测小/大端并做出相应的反应我上面展示的代码示例适用于小端(x86)。

答案 3 :(得分:0)

有关类似问题的here,请参阅我的回答。 这与Jimmy的答案一样,是不安全的记忆操作,但对消费者来说是一种更“友好”的方式。它允许您将byte数组视为UInt64数组。