我发现了一个博客条目,它建议有时c#编译器可能决定将数组放在堆栈上,而不是堆上:
通过堆栈分配提高性能(.NET内存管理:第2部分)
这家伙声称:
编译器有时也会决定自己把东西放到堆栈上。我用TestStruct2做了一个实验,在这个实验中,我给它分配了一个不安全的和正常的上下文。在不安全的上下文中,数组被放到堆上,但是在正常的上下文中,当我查看内存时,数组实际上是在堆栈上分配的。
,有人能证实吗?
我试图重复他的例子,但每次我尝试在堆上分配数组。
如果c#编译器可以在不使用“不安全”关键字的情况下完成这样的操作,我将特别注意它。我有一个在许多小字节数组(8-10字节长)上工作的代码,所以对每个新字节使用堆.浪费时间和内存(尤其是堆中的每个对象都有垃圾收集器所需的8个字节)。
编辑:--我只想描述一下为什么它对我很重要:
我正在编写与Gemalto.NET智能卡通信的库,它可以让.net代码在其中工作。当我调用返回某项内容的方法时,智能卡将返回8个字节,该字节描述了返回值的确切类型。这8个字节是通过使用md5哈希和一些字节数组连接来计算的。
问题是,当我有一个不为我所知的数组时,我必须扫描加载在应用程序中的所有程序集中的所有类型,对于每个类型,我必须计算这8个字节,直到找到相同的数组。
我不知道如何找到这类人,所以我尽量加快速度。
发布于 2009-07-14 08:00:52
从你的台词:
我有一个处理许多小字节数组(8-10字节长)的代码。
就个人而言,我更感兴趣的是分配一个备用缓冲区,以便您的代码的不同部分可以重用(同时处理相同的块)。那么您就没有任何要担心的创建/GC了。在大多数情况下(缓冲区用于非常谨慎的操作)使用scratch-缓冲区,您甚至可以始终假设它是“所有的”--也就是说,每一种需要它的方法都可以假设它们可以在零开始写入。
我在一些二进制序列化代码(同时编码数据)中使用了这种单缓冲区方法;它极大地提高了性能。在我的例子中,我在序列化的各个层之间传递一个"context“对象(封装了划痕缓冲区、输出流(带有一些附加的本地缓冲)和一些其他奇怪的东西)。
发布于 2009-07-17 14:10:37
这篇链接文章的作者。
在不安全上下文之外强制堆栈分配似乎是不可能的。这很可能是防止某些类堆栈溢出情况的情况。
相反,我建议使用内存回收器类,它将根据需要分配字节数组,但也允许您在以后“提交”它们以供重用。它就像保持一个未使用的字节数组堆栈一样简单,当列表为空时,分配新的字节数组。
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);
}如果您试图将哈希与类型匹配,那么最好的方法是使用字典进行快速查找。在这种情况下,您可以在启动时加载所有相关类型,如果这导致程序启动变得太慢,您可能希望在第一次使用每个类型时考虑缓存它们。
发布于 2009-07-14 07:37:51
System.Array (表示数组的类)是一个引用类型,它存在于堆中。只有在使用不安全代码时,堆栈上才能有数组。
我看不出你提到的那篇文章中有什么不同的地方。如果要分配堆栈数组,可以执行以下操作:
decimal* stackAllocatedDecimals = stackalloc decimal[4];就我个人而言,我不会费心--你认为通过这种方法你能获得多少成绩?
不过,这个CodeProject文章可能对您有用。
https://stackoverflow.com/questions/1123939
复制相似问题