Web 应用程序中 IronPython 内存泄漏的问题

Posted

技术标签:

【中文标题】Web 应用程序中 IronPython 内存泄漏的问题【英文标题】:Problems with IronPython memory leaks in web application 【发布时间】:2011-03-28 14:49:48 【问题描述】:

有没有人成功让 IronPython 在 Web 环境中顺利运行?我遇到了一些问题。

第一个问题,我实际上并没有运行任何 IronPython 特定的脚本,我正在实现 Pygments 库,因此我可以获得服务器端语法突出显示。该库大约有 20 多个文件。

除了最新的 IronPython 版本无法将脚本编译成 DLL(由于 this issue),我只需将所有文件和依赖项复制到我的 bin 文件夹即可成功运行。

问题是,我去查看我的 w3wp.exe 进程在进行高亮显示时的表现,并注意到一些令人瞩目的问题:

即使在 Cassini 下的一个完全基本的、空的网站中,使用 SQL 词法分析器突出显示代码 select * from table 也会导致每次执行它时都会跳转 10MB(页面刷新)...我明确地关闭了引擎并在单个函数调用中使用LightweightScopes。它从大约 30MB 开始,大约 20 次刷新后大约为 150MB。

1234563电脑爬行。这不会发生在空的测试站点中,并且在具有相同确切代码的控制台应用程序中根本没有问题。其他的词法分析器(如 C#)不会导致巨大的内存泄漏,但确实具有每次调用函数时增加内存的相同效果。

这让我相信这是一个特定于网络的问题,考虑到控制台应用程序没有任何问题(但实例化运行时确实会导致内存增加 20MB)。

我正在使用 2.7 IPY 版本和 1.4 版本的 Pygments。

我目前没有确切的代码,但它看起来像:

var options = something;
options["LightweightScopes"] = ScriptRuntimeHelpers.True; // from another SO post, 'true' didn't seem to work
var engine = Python.CreateEngine(options);
//
// set up search paths here...
//
dynamic scope = whatever;
ScriptSource source = engine.CreateScriptSourceFromFile("myscript.py");

// Execute? Compile? It populates the scope at this point...
source.Compile(scope);

// execute (code, lexer name, style)
// this is a python function I have that calls the Pygments code
var highlighted = scope.generate_html("select * from table", "sql", "monokai");

engine.Shutdown();
return highlighted;

就像我说的,我将相同的代码复制到:a) 控制台应用程序,b) 一个全新的空 Web 应用程序,c) 我原来的 Web 应用程序。控制台应用程序不会泄漏内存,但 Web 应用程序会。

我还使用本机 Python (python myscript.py) 和 IPY (ipy myscript.py) 执行了该函数,并且都没有任何内存泄漏。

我是否缺少一些最佳实践来处置运行时?我计划在共享环境中运行它,因此在不同的应用程序池中实例化引擎的可能解决方法可能对我不起作用(另外,200MB/s 的巨大泄漏是一种阻碍)。

目前,除非有人有灵丹妙药,否则我打算废弃我的代码并使用 javascript 语法荧光笔。这真的很不幸,因为 Pygments 很棒......

【问题讨论】:

您真的在创建引擎并按请求执行代码吗?如果是这样,您可能应该切换到从 scriptSource.Compile() 保存结果,然后在编译后的代码上重复调用 Execute。 迪诺说了什么。另外,您的控制台应用程序是格式化多次,还是只格式化一次然后退出? @Dino,是的,我一直将它用作单例,将引擎和脚本源保持为静态变量,但我也会尝试按照您的建议进行操作。 @Jeff,我曾经运行过一次......我认为网络应用程序中的问题出现在第一个请求上,所以它也应该出现在应用程序启动时,我有一个 @987654328 @我等了,我没有看到内存上升。 【参考方案1】:

这是一个很长的故事。 (TLDR,对不起)。这是 .NET,您最有可能关注的是堆碎片而不是内存耗尽。

如果你真的在泄漏内存,那么你持有引用的时间太长了。回顾你的 IDisposables(尤其是列表理解可能会受到伤害,尤其是在 Linqy 的东西上,比如 orderby 和 distinct)。

我曾经让一个应用程序的运行速度提高了 2 倍,当它通过在我必须驱动一个大进程的最大枚举上添加一个简单的 .ToList() 来耗尽/分割堆时可靠地失败了。

.NET 有很好的内存分析器,但我目前只知道如何操作 mono --profiler(坏内存)。一个简单的 google 将帮助您找到可以在您的环境中使用的分析器:让它准确地告诉您 什么 对象分配在哪里使您的堆碎片化


附言。因为我看到您在第二次扫描您的问题时将矛头指向 Web 应用程序,所以我要补充一点:检查会话状态(应用程序、会话)中持有哪些引用(间接)。

【讨论】:

以上是关于Web 应用程序中 IronPython 内存泄漏的问题的主要内容,如果未能解决你的问题,请参考以下文章

Tomcat如何检测内存泄漏

如何测试 Web 应用程序的内存泄漏?

LDAP PermGen 内存泄漏

在 Rails 应用程序中查找内存泄漏

关于内存泄漏

记一次 .NET 某电厂Web系统 内存泄漏分析