C# 内存有效递归

C# 内存有效递归,c#,memory-management,C#,Memory Management,我用C#编写了一个应用程序,可以生成字母、数字和少数特殊字符组合中的所有单词 问题是它的内存效率不高,因为它正在适应递归和一些类似于列表的集合 有没有办法让它在内存有限的环境中运行 Umair将它转换成一个好吧,你显然不能将中间结果存储在内存中(除非你有某种荒谬的计算机在你的支配之下);您必须将结果写入磁盘 递归深度不是所考虑的字符数的结果-它是由您愿意考虑的最大字符串长度决定的。 例如,我安装的python 2.6.2的默认递归限制设置为1000。值得商榷的是,给定一个字符集,我应该能够在这个

我用C#编写了一个应用程序,可以生成字母、数字和少数特殊字符组合中的所有单词

问题是它的内存效率不高,因为它正在适应递归和一些类似于列表的集合

有没有办法让它在内存有限的环境中运行


Umair

将它转换成一个

好吧,你显然不能将中间结果存储在内存中(除非你有某种荒谬的计算机在你的支配之下);您必须将结果写入磁盘

递归深度不是所考虑的字符数的结果-它是由您愿意考虑的最大字符串长度决定的。 例如,我安装的python 2.6.2的默认递归限制设置为1000。值得商榷的是,给定一个字符集,我应该能够在这个限制内生成所有可能的1-1000长度字符串(现在,我认为递归限制适用于总堆栈深度,因此实际限制可能小于1000)

编辑(添加python示例): 下面的python代码片段将生成您所要求的内容(将自身限制为给定的运行时堆栈限制):

通过尝试/捕获StackOverflowException,可以在C#中产生基本相同的结果。当我键入此更新时,脚本正在运行,占用了我的一个核心。然而,内存使用量在小于7MB时是恒定的。现在,我只是打印到stdout,因为我对捕获结果不感兴趣,但我认为这证明了上述观点

示例附录: 有趣的注意:仔细观察运行的进程,python实际上与上面的示例绑定了I/O。它只使用了我7%的CPU,而内核的其余部分必然会在我的命令窗口中呈现结果。最小化窗口可以使python的CPU使用率上升到总CPU使用率的40%,这是在一台双核机器上。

不幸的是,C#编译器无法执行,这是您希望在这种情况下发生的事情。CLR支持它,但您不应该依赖它


也许在字段左侧,但也许您可以用F#编写程序的递归部分?通过这种方式,您可以利用有保证的尾部调用优化,并重用C#代码中的部分。虽然学习曲线陡峭,但F#更适合于这些组合任务。

还有一点需要考虑:当您连接或使用其他方法在C#中生成字符串时,它会占用自己的内存,可能会停留一段时间。如果您正在生成数以百万计的字符串,您可能会注意到一些性能阻力


如果您不需要保留大量字符串,我将查看是否有其他方法可以避免生成字符串。例如,可能您有一个字符数组,当您在字符组合中移动时,它会不断更新,如果您要将它们输出到一个文件中,您可以一次输出一个字符,这样您就不必构建字符串。

嗯……我不确定我和谁在一起,但我找到了解决方案。我使用了不止一个过程,一个与用户交互,另一个用于查找单词组合。另一个进程找到5000个单词,保存并退出。正在通过WCF实现通信。当process quits=释放内存时,这看起来很好。

好吧,让我们看看你有什么。.递归在处理树、图时可以非常简洁。@Hamish递归可以很简洁是的,但在这个问题的上下文中不是这样。直接递归可能需要大量的堆栈空间和大量的堆栈帧“推送和弹出”。这个站点的名称与这个场景有关联……编写内存高效递归算法的关键是限制堆栈上的数据量。当您无法做到这一点时,唯一真正的解决方案是切换到iteration.dependens。若您使用堆栈空间来维护状态,那个么切换到迭代并没有帮助。你必须以某种方式重新构造你的算法。如果它使用堆栈空间是因为你有一个编译器没有优化的尾部调用,那么你切换到迭代就可以了,尽管在这种情况下我会责怪编译器。递归只有在编译器为其优化而构建时才会扩展(比如在面对尾部递归时丢弃旧堆栈,即递归调用是函数做的最后一件事,LISP eg非常欣赏这一点)在这种情况下,我相信海报将所有结果存储在一个列表中,这意味着他正试图使用~68^8~=450000000000000*8字节的内存。哈哈,解决方案是将结果转储到某个archiver类,然后该类将决定何时是编写另一个文件的好时机以及文件的名称。
from string import ascii_lowercase

def generate(base="", charset=ascii_lowercase):
    for c in charset:
        next = base + c
        yield next
        try:
            for s in generate(next, charset):
                yield s
        except:
            continue

for s in generate():
    print s