【发布时间】:2011-07-15 04:49:48
【问题描述】:
我不习惯使用指针(例如 C++)进行编码,也不习惯使用不安全岛:只有“安全”的 C#。 现在我想在 C# 中为 .Net Micro Framework 实现一个函数,其中紧凑性和性能非常重要。 基本上,我会收集 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 < ArraySize);
}
Console.ReadKey();
}
unsafe static void Test5()
{
_structPtr->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;
}
}
比以下更安全的方式(例如,)的改进不是那么高(177 毫秒与 224 毫秒),但无论如何它是显着的。
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;
}
注意:我已经剪掉了一些代码,但我认为它已经足够清晰了。
我的问题是:我通过将“固定”指针复制到另一个未固定的指针而做出的“技巧”是否可靠?...但是您可以假设所有数据都是静态分配的,因此应该固定。 先感谢您。 干杯
【问题讨论】:
-
澄清一下,Test3 还是 Test5 更快?
-
您是否在没有一次性 JITting 的情况下进行了测量?我的意思是您是否尝试运行一次托管函数然后循环测量它? JITting 只发生一次,因此如果将其包含在时间总和中,与不安全的方式相比将是一个糟糕的比较。
-
为什么 AnX 方法返回一个 int?你不能让他们退回短裤并跳过演员表吗?这会提高性能吗?此外,从
fixed语句中获取指向托管缓冲区的指针似乎是一个非常糟糕的主意。我不确定,但我认为如果 GC 挡道,那可能会受到伤害。 -
@jde - 没有抖动,IL 被解释。放弃所有关于效率的假设。
-
哦,谢谢汉斯,我不知道关于 .NET 微框架的事实......