不安全的C#技巧提高速度

我不习惯使用指针(例如C ++)编码,也不习惯使用不安全的岛:只使用“安全”C#。 现在我想在.Net Micro Framework的C#中实现一个函数,其中紧凑性和性能非常重要。 基本上,我会收集4个短裤,从而填充缓冲区(例如字节数组)。 假设每个样本都是这样的:

struct MyStruct { public short An1; public short An2; public short An3; public short An4; } 

每个样本都是通过计时器事件收集的,因此我无法循环(有几个原因)。 我已经尝试了很多方法来有效地做到这一点,但表现最好的似乎是这个:

 unsafe struct MyStruct2 { public fixed byte Buffer[Program.BufferSize]; } unsafe class Program { public const int BufferSize = 0x1000; public const int ArraySize = BufferSize / 8; static MyStruct2 _struct2 = new MyStruct2(); static MyStruct* _structPtr; unsafe static void Main(string[] args) { int iter = 5000; //just for simulate many cycles for (int i = 0; i < iter; i++) { //let's make a trick! fixed (byte* ptr = _struct2.Buffer) _structPtr = (MyStruct*)ptr; _structIndex = 0; do { Test5(); } while (++_structIndex An1 = (short)An1(); _structPtr->An2 = (short)An2(); _structPtr->An3 = (short)An3(); _structPtr->An4 = (short)An4(); _structPtr++; } //simulations of ADC reading static int An1() { return 0x1111; } static int An2() { return 0x2222; } static int An3() { return 0x3333; } static int An4() { return 0x4444; } } 

对以下更安全的方式的改进 – 例如 – 不是那么高(177ms对224ms),但无论如何它都很重要。

  static MyStruct Test3() { var data = new MyStruct(); data.An1 = (short)An1(); data.An2 = (short)An2(); data.An3 = (short)An3(); data.An4 = (short)An4(); return data; } 

注意:我已经删除了一些代码,但我认为它已经足够清楚了。

我的问题是:我通过将“固定”指针复制到另一个未固定的“技巧”可能是否可靠?…但是你可以假设所有数据都是静态分配的,所以应该固定。 先感谢您。 干杯

我不认为代码是安全的。 在_structPtr = (MyStruct*)ptr ,在固定范围内,然后在假设_struct2不会移动的情况下继续将数据放入_structPtr。 虽然你是正确的,它不会被GCed,但这并不意味着GC在内存压缩期间不会移动它。 .NET Compact Framework仍然是垃圾收集,我认为它压缩了内存,而不是让它分散。

例如,如果GC删除了在_struct2之前在堆上分配的瞬态(非静态)对象,那么该结构使用的内存可能会移动到该瞬态对象使用的空闲空间中。 此时_structPtr指向未使用的内存。

修改Test3()以获取ref MyStruct data帮助吗?

另外,checkout [StructLayout(LayoutKind.Explicit)][FieldOffset(...)]将允许您使用多种方式访问​​其中的相同数据。 在你的情况下,作为4个字节或1个int或(可能)1个4字节的数组。

在我广泛使用的一些代码中,从不同的post看这个例子 。 您有正确的想法,只需要设置FieldOffset()值,然后在访问数据时使用fixed()关键字。

这种方法非常可靠,但速度并不快。 我使用它的原因是因为当我有很多字段时,我想要一种快速的方式来访问它们作为一个数组。

我不认为你的“伎俩”是个问题。 没有人关心你如何索引内存,或者你用它来完成它的偏移量。 我认为您需要注意其他人的建议,并确保使用StructLayout.Sequential或.Explicit控制结构的布局。 同时观看尺寸和包装选项。

另一个问题是,您需要在固定块中完成所有工作。

 fixed (byte* ptr = struct2.Buffer) { var structPtr = (MyStruct*)ptr; var structIndex = 0; do { Test5(structPtr); } while (++structIndex < ArraySize); } 

就个人而言,我认为你偶然发现了一些Micro-Optimization影院,使用安全的C#代码会更好。 根据你给出的数字,(224x10 ^ -3 - 177x10 ^ -3)产生47ms,除以5000次迭代,每次迭代就会得到9.4us(9.4x10 ^ -6)(假设windows没有做其他事情)时间)。