c#编译器决定自己使用stackalloc吗?

时间:2009-07-14 07:23:22

标签: c# compiler-construction stackalloc

我找到了一个博客条目,表明有时c#编译器可能会决定将数组放在堆栈而不是堆上:

Improving Performance Through Stack Allocation (.NET Memory Management: Part 2)

这家伙声称:

  

编译器有时也会决定将内容放在堆栈中。我在TestStruct2上做了一个实验,我在其中分配了一个不安全和正常的上下文。在不安全的上下文中,数组被放在堆上,但在正常的上下文中,当我查看内存时,数组实际上已在堆栈上分配。

有人可以证实吗?
我试图重复他的例子,但每次我尝试在堆上分配数组。

如果c#编译器可以在不使用'unsafe'关键字的情况下执行此类操作,我特别感兴趣。我有一个代码正在处理许多小字节数组(8-10个字节长),所以使用堆为每个新字节[...]浪费时间和内存(特别是堆上的每个对象有8字节开销需要垃圾收集器。)

编辑:我只是想描述一下这对我来说很重要:
我正在编写与Gemalto.NET智能卡通信的库,该智能卡可以使用.net代码。当我调用返回某个东西的方法时,智能卡返回8个字节,它描述了确切的返回值类型。这8个字节是使用md5哈希和一些字节数组连接计算的 问题是,当我有一个我不知道的数组时,我必须扫描应用程序中加载的所有程序集中的所有类型,并且每个我必须计算这8个字节,直到找到相同的数组。
我不知道其他找到类型的方法,所以我试图尽可能加快速度。

3 个答案:

答案 0 :(得分:4)

此处链接文章的作者。

似乎不可能在不安全的上下文之外强制堆栈分配。这可能是防止某些类堆栈溢出情况的情况。

相反,我建议使用内存回收器类,它将根据需要分配字节数组,但也允许您在之后“将其转入”以供重用。它就像保留一堆未使用的字节数一样简单,当列表为空时,分配新的数组。

Stack<Byte[]> _byteStack = new Stack<Byte[]>();

Byte[] AllocateArray()
{
Byte[] outArray;
if (_byteStack.Count > 0)
  outArray = _byteStack.Pop(); 
else
  outArray = new Byte[8];
return outArray;
}

void RecycleArray(Byte[] inArray)
{
  _byteStack.Push(inArray);
}

如果您尝试将哈希与类型匹配,那么最好的想法是使用词典进行快速查找。在这种情况下,您可以在启动时加载所有相关类型,如果这会导致程序启动变得太慢,您可能需要在第一次使用每种类型时考虑缓存它们。

答案 1 :(得分:2)

从你的行:

  

我有一个代码可以处理许多小字节数组(长8-10个字节)

就个人而言,我更感兴趣的是在代码的不同部分可以重复使用的某个地方分配备用缓冲区(同时处理相同的块)。然后你没有任何创建/ GC担心。在大多数情况下(缓冲区用于非常谨慎的操作)和暂存缓冲区,你甚至可以假设它是“你的全部” - 即每个需要它的方法都可以假设它们可以从零开始写入。 / p>

我在一些二进制序列化代码中使用这种单缓冲区方法(在编码数据时);这是对性能的巨大推动。在我的例子中,我在序列化层之间传递一个“上下文”对象(它封装了临时缓冲区,输出流(带有一些额外的本地缓冲)和一些其他奇怪的东西)。

答案 2 :(得分:1)

System.Array(表示数组的类)是引用类型并且存在于堆上。如果使用不安全的代码,则堆栈中只能有一个数组。

在你提到的那篇文章中,我看不出它的含义。如果你想要一个堆栈分配的数组,你可以这样做:

decimal* stackAllocatedDecimals = stackalloc decimal[4];

就我个人而言,我不会打扰 - 您认为通过这种方法可以获得多少性能?

CodeProject article可能对您有用。