结构与类内存开销

时间:2012-02-09 14:01:09

标签: c# out-of-memory

我正在编写一个应用程序,它将创建数千个小对象并以递归方式将它们存储在数组中。通过“递归”,我的意思是K的每个实例将具有K实例的数组,其将具有K实例的数组,依此类推,并且该数组+一个int字段是唯一的属性+一些方法。我发现内存使用量增长得非常快,即使是少量数据 - 大约1MB),当我处理的数据大约为10MB时,我得到“OutOfMemoryException”,更不用说什么时候它更大(我有4GB的RAM) :)。那么你建议我做什么?我想,如果我创建单独的V类来处理这些对象,那么K的实例将只有K的+一个整数字段的数组并使K作为结构而不是类,它应该优化一些东西 - 没有垃圾收集和东西......但这有点挑战,所以在开始全部重写之前,我宁愿问你这是不是一个好主意:)。

编辑: 好的,一些抽象代码

public void Add(string word) {
    int i;
    string shorter;

    if (word.Length > 0) {
        i = //something, it's really irrelevant

        if (t[i] == null) {
            t[i] = new MyClass();
        }

        shorterWord = word.Substring(1); 

        //end of word
        if(shorterWord.Length == 0) {
            t[i].WordEnd = END;
        }

        //saving the word letter by letter
        t[i].Add(shorterWord);
        }
    }
}

5 个答案:

答案 0 :(得分:4)

对于我来说,当我深入研究这个时,我有以下假设(它们可能是不精确的;我对程序员来说已经老了)。类具有额外的内存消耗,因为需要引用来解决它。存储引用,32位编译需要Int32大小的指针。总是在堆上分配(不记得C ++是否有其他可能性,我会冒险吗?)

简短的回答,在本文中找到,Object有一个12字节的基本足迹+4个可能未使用的字节,具体取决于你的类(毫无疑问与填充有关)。

http://www.codeproject.com/Articles/231120/Reducing-memory-footprint-and-object-instance-size

您将遇到的其他问题是Arrays也有开销。可能的办法是将自己的偏移量管理为更大的数组或数组。反过来越接近某种更有效的语言就越适合。

我不确定是否有库可以高效的方式为小对象提供存储。可能是。

我接受它,使用Structs,在一个大型数组中管理你自己的偏移量,并使用适当的包装说明(如果它为你服务)(虽然我怀疑每次你不均匀地解决这个问题时会花费一些额外的指令)打包数据)

[StructLayout(LayoutKind.Sequential, Pack = 1)]

答案 1 :(得分:2)

你的筹码正在爆炸。

迭代地而不是递归地执行。

你没有把系统堆叠起来,你把代码堆叠起来,10K函数调用会把它吹出水面。

你需要适当的尾递归,这只是一个迭代的黑客。

答案 2 :(得分:0)

确保系统中有足够的内存。超过100mb +等。这真的取决于你的系统。链接列表,递归对象就是你正在看的。如果你继续递归,它将达到内存限制并且将抛出nomemoryexception。确保跟踪任何程序的内存使用情况。没有什么是无限的,特别是记忆。如果内存有限,请将其保存到磁盘。

看起来你的代码中存在无限递归,并且抛出内存不足。检查代码。应该有递归代码的开始和结束。否则它会在某个时刻超过10 TB的内存。

答案 3 :(得分:0)

只需列出您的递归算法并清理变量名称。如果您正在进行BFS类型的遍历并将所有对象保留在内存中,则将耗尽内存。例如,在这种情况下,请将其替换为DFS。

修改1:

您可以通过估算生成的项目然后一次分配大量内存来加快算法速度。随着算法的进展,填满分配的内存。这减少了碎片和重新分配。复制全数组操作。 尽管如此,在完成对这些生成的单词的操作后,您应该从数据结构中删除它们,以便它们可以进行GC编辑,这样就不会耗尽内存。

答案 4 :(得分:0)

您可以使用更好的数据结构 即每个字母可以是一个字节(a-0,b-1 ......)。每个单词片段都可以被索引,尤其是子串 - 你应该以更少的内存(虽然性能损失)逃脱