我在每个线程迭代后打印出可用空间,以便观察其缓慢下降。现在有趣的是,它不是每次都会减少。有时在迭代后,可用内存保持不变。
我正在使用从源代码构建的Perl 5.8.8,在Linux 2.6上运行。
有人有任何想法或建议吗,甚至是可能导致这种情况的建议?我考虑升级我的Perl到一个更高版本,以排除Perl核心内存泄漏的可能性。
更新:这可能是线程堆栈大小问题吗?我是否分配了比所需更多的堆栈内存。当我创建线程时,我没有改变设置。我应该吗?线程文档说默认值通常为16MB,具体取决于系统。16x10个线程=160MB->这可能是罪魁祸首。你怎么看?
更新:我构建并安装了Perl 5.12.1,并重新构建了模块和其他一切。现在已经运行脚本约一个小时了,这是我的发现。内存使用现在可管理,但不是理想的。
- 刚开始生成线程后,我的线程似乎要少一些。从分配给我的10个线程的大约60-66MB下降到了45-50MB左右。
- 经过一些迭代,它们的使用量总共增加了3MB(与之前大致相同)。
- 到这个点为止,这正是我预期的。所有的内存都用在了生成线程上,然后只有一点点变量用于我的线程。这是我不喜欢的部分。运行了大约10分钟后,我失去了额外的65MB!为什么会这样?如果已经迭代了几次,只用了3MB,为什么还要继续分配?
- 它已经运行了一个半小时,它们不再使用额外的65MB了,而是额外的84MB!
- 它慢慢地占用更多的内存,但奇怪的是每次迭代时可用内存的数量并没有减少。我在每次迭代之前和之后打印出可用内存,并且它会在一段时间内保持不变或者在某个数字周围波动,然后突然变化5-10MB。我不能让它运行超过一两天,因为它开始接近我可用内存的80/90%。
还有其他的想法吗?我已经取消了所有变量的定义。
更新: 我真的希望最后能重新编译Perl与glibc,因为我发现在某些Linux版本上它会segfault。所以自从我上次发布以来,我进一步探索了哈希表中的循环可能性。没有发现什么。所以我花了最近几天时间分析我的子例程并缓存任何在另一个迭代中使用的东西。每次都会创建很多新的东西,即使我明确地取消定义所有东西,Perl也不会清理所有东西。所以如果它不合作,我就不会摧毁它。看看缓存我的对象是否有所帮助。稍后会发布内存使用情况统计数据。
更新: 嗯,非常奇怪。即使缓存我的数据以便以后重用,内存增长速度也大致相同。现在开始较高,因为我正在缓存,但随后持续上升,尽管它主要使用我的缓存对象。这很令人困惑。猜想是时候尝试glibc了……否则这只是选择Perl的一个缺点,将不得不每隔几天重启服务器。
更新: 没有缓存,没有glibc,再次尝试。一段时间内运行良好,几个小时后开始增长。只是想让你看到一个图表。
http://tinypic.com/r/311nc08/3
http://i32.tinypic.com/311nc08.jpg
更新: 这里是一份记录了每个线程在大约一分钟内使用前后的空闲内存的日志摘录。也许这可以帮助某些人更好地理解问题。它似乎稳定了一段时间,然后偶尔会像这样吞噬更多的内存。在这里,我失去了近40 MB!
[9:8:30, Fri Jul 23, 2010] [0] Memory usage at end thread 1: 253.812736MB (obj cache: 136)
[9:8:30, Fri Jul 23, 2010] [0] Memory usage at idle thread 1: 253.812736MB (obj cache: 136)
[9:8:34, Fri Jul 23, 2010] [204] Sending data to thread
[9:8:34, Fri Jul 23, 2010] [0] 3 - Creating a new obj
[9:8:34, Fri Jul 23, 2010] [206] Sending data to thread
[9:8:34, Fri Jul 23, 2010] [0] 4 - Creating a new obj
[9:8:35, Fri Jul 23, 2010] [0] Memory usage at end thread 3: 253.812736MB (obj cache: 136)
[9:8:35, Fri Jul 23, 2010] [0] Memory usage at idle thread 3: 253.812736MB (obj cache: 136)
[9:8:35, Fri Jul 23, 2010] [0] Memory usage at end thread 4: 253.812736MB (obj cache: 136)
[9:8:35, Fri Jul 23, 2010] [0] Memory usage at idle thread 4: 253.812736MB (obj cache: 136)
[9:8:41, Fri Jul 23, 2010] [225] Sending data to thread
[9:8:41, Fri Jul 23, 2010] [0] 2 - Creating a new obj
[9:8:42, Fri Jul 23, 2010] [0] Memory usage at end thread 2: 253.681664MB (obj cache: 136)
[9:8:42, Fri Jul 23, 2010] [0] Memory usage at idle thread 2: 253.681664MB (obj cache: 136)
[9:8:47, Fri Jul 23, 2010] [243] Sending data to thread
[9:8:47, Fri Jul 23, 2010] [0] 1 - Creating a new obj
[9:8:48, Fri Jul 23, 2010] [0] Memory usage at end thread 1: 253.935616MB (obj cache: 136)
[9:8:48, Fri Jul 23, 2010] [0] Memory usage at idle thread 1: 253.935616MB (obj cache: 136)
[9:9:1, Fri Jul 23, 2010] [277] Sending data to thread
[9:9:1, Fri Jul 23, 2010] [0] 3 - Creating a new obj
[9:9:2, Fri Jul 23, 2010] [280] Sending data to thread
[9:9:2, Fri Jul 23, 2010] [0] 4 - Creating a new obj
[9:9:2, Fri Jul 23, 2010] [0] Memory usage at end thread 3: 253.935616MB (obj cache: 136)
[9:9:2, Fri Jul 23, 2010] [0] Memory usage at idle thread 3: 253.935616MB (obj cache: 136)
[9:9:3, Fri Jul 23, 2010] [283] Sending data to thread
[9:9:3, Fri Jul 23, 2010] [0] 2 - Creating a new obj
[9:9:4, Fri Jul 23, 2010] [284] Sending data to thread
[9:9:4, Fri Jul 23, 2010] [0] 1 - Creating a new obj
[9:9:4, Fri Jul 23, 2010] [0] Memory usage at end thread 2: 253.935616MB (obj cache: 136)
[9:9:4, Fri Jul 23, 2010] [0] Memory usage at idle thread 2: 253.935616MB (obj cache: 136)
[9:9:5, Fri Jul 23, 2010] [287] Sending data to thread
[9:9:5, Fri Jul 23, 2010] [0] 3 - Creating a new obj
[9:9:5, Fri Jul 23, 2010] [0] Memory usage at end thread 4: 253.93152MB (obj cache: 136)
[9:9:5, Fri Jul 23, 2010] [0] Memory usage at idle thread 4: 253.93152MB (obj cache: 136)
[9:9:6, Fri Jul 23, 2010] [290] Sending data to thread
[9:9:6, Fri Jul 23, 2010] [0] 2 - Creating a new obj
[9:9:7, Fri Jul 23, 2010] [0] Memory usage at end thread 3: 253.804544MB (obj cache: 136)
[9:9:7, Fri Jul 23, 2010] [0] Memory usage at idle thread 3: 253.804544MB (obj cache: 136)
[9:9:7, Fri Jul 23, 2010] [0] Memory usage at end thread 1: 253.804544MB (obj cache: 136)
[9:9:7, Fri Jul 23, 2010] [0] Memory usage at idle thread 1: 253.804544MB (obj cache: 136)
[9:9:9, Fri Jul 23, 2010] [0] 4 - Creating a new obj
[9:9:9, Fri Jul 23, 2010] [301] Sending data to thread
[9:9:9, Fri Jul 23, 2010] [0] 3 - Creating a new obj
[9:9:9, Fri Jul 23, 2010] [302] Sending data to thread
[9:9:9, Fri Jul 23, 2010] [0] 1 - Creating a new obj
[9:9:10, Fri Jul 23, 2010] [0] 3 - Creating a new obj
[9:9:11, Fri Jul 23, 2010] [0] 3 - Creating a new obj
[9:9:11, Fri Jul 23, 2010] [0] Memory usage at end thread 4: 253.93152MB (obj cache: 136)
[9:9:11, Fri Jul 23, 2010] [0] Memory usage at idle thread 4: 253.93152MB (obj cache: 136)
[9:9:12, Fri Jul 23, 2010] [308] Sending data to thread
[9:9:12, Fri Jul 23, 2010] [0] 4 - Creating a new obj
[9:9:13, Fri Jul 23, 2010] [0] Memory usage at end thread 1: 253.804544MB (obj cache: 136)
[9:9:13, Fri Jul 23, 2010] [0] Memory usage at idle thread 1: 253.804544MB (obj cache: 136)
[9:9:14, Fri Jul 23, 2010] [0] Memory usage at end thread 4: 253.804544MB (obj cache: 136)
[9:9:14, Fri Jul 23, 2010] [0] Memory usage at idle thread 4: 253.804544MB (obj cache: 136)
[9:9:14, Fri Jul 23, 2010] [0] Memory usage at end thread 3: 253.93152MB (obj cache: 136)
[9:9:14, Fri Jul 23, 2010] [0] Memory usage at idle thread 3: 253.93152MB (obj cache: 136)
[9:9:15, Fri Jul 23, 2010] [313] Sending data to thread
[9:9:15, Fri Jul 23, 2010] [0] 1 - Creating a new obj
[9:9:16, Fri Jul 23, 2010] [0] Memory usage at end thread 2: 214.482944MB (obj cache: 136)
[9:9:16, Fri Jul 23, 2010] [0] Memory usage at idle thread 2: 214.482944MB (obj cache: 136)
[9:9:16, Fri Jul 23, 2010] [315] Sending data to thread
[9:9:16, Fri Jul 23, 2010] [0] 4 - Creating a new obj
[9:9:17, Fri Jul 23, 2010] [0] Memory usage at end thread 1: 214.355968MB (obj cache: 136)
[9:9:17, Fri Jul 23, 2010] [0] Memory usage at idle thread 1: 214.355968MB (obj cache: 136)
[9:9:18, Fri Jul 23, 2010] [316] Sending data to thread
[9:9:18, Fri Jul 23, 2010] [0] 3 - Creating a new obj
[9:9:18, Fri Jul 23, 2010] [317] Sending data to thread
[9:9:18, Fri Jul 23, 2010] [0] 2 - Creating a new obj
[9:9:18, Fri Jul 23, 2010] [318] Sending data to thread
[9:9:18, Fri Jul 23, 2010] [0] 1 - Creating a new obj
[9:9:19, Fri Jul 23, 2010] [0] Memory usage at end thread 4: 214.355968MB (obj cache: 136)
[9:9:19, Fri Jul 23, 2010] [0] Memory usage at idle thread 4: 214.355968MB (obj cache: 136)
[9:9:19, Fri Jul 23, 2010] [0] Memory usage at end thread 1: 214.355968MB (obj cache: 136)
[9:9:19, Fri Jul 23, 2010] [0] Memory usage at idle thread 1: 214.355968MB (obj cache: 136)
[9:9:20, Fri Jul 23, 2010] [0] Memory usage at end thread 3: 214.482944MB (obj cache: 136)
[9:9:20, Fri Jul 23, 2010] [0] Memory usage at idle thread 3: 214.482944MB (obj cache: 136)
[9:9:20, Fri Jul 23, 2010] [0] Memory usage at end thread 2: 214.482944MB (obj cache: 136)
[9:9:20, Fri Jul 23, 2010] [0] Memory usage at idle thread 2: 214.482944MB (obj cache: 136)
更新(8/12/2010):我刚刚使用带有线程和系统malloc的新编译版本的Perl 5.12运行了一天。奇怪的是,我得到了相同的行为。每次失去几个MB,缓慢地。我可能会尝试使用Valgrind来查看我为什么失去它。然而,当我在玩其他东西时,我想到了另一件事情。我的脚本创建并销毁(据称)许多SSL套接字。像IO::Socket::SSL这样广泛使用的模块是否可能泄漏一点?或者是OpenSSL?(使用v0.9.8o)。要尝试同步访问SSL模块,看看它是否有任何影响,可能会遇到线程访问它的问题。
更新:尝试在每个线程中单独加载模块,更快的内存使用率。尝试锁定使用套接字函数的区域,以便只有一个线程同时使用它们,仍然会像以前一样丢失内存。将工作线程数从4增加到10,完成相同数量的工作。内存没有持续30分钟。这让我相信,它要么是Perl内部的线程实现问题,要么是堆栈问题(不是故意的)。我尝试使用内置线程方法更改堆栈大小,但结果相同。要寻找另一种方法。也许是一种更低级别的方法。增加线程数会使内存更快地消耗...似乎与线程的堆栈实现或堆栈的大小有关。
更新(9/15/2010):在IO::Socket::SSL文档中发现了这个有趣的片段...
这是因为需要循环引用才能使IO::Socket::SSL套接字同时像对象和全局引用一样工作。
"循环引用"?另一个可能的解释是,即使我明确地取消引用了它们,这些套接字也会一直保留一段时间。要研究Weaken,看看它是否对套接字产生影响。如果我发现任何有趣的事情,我会告诉你的。
已解决(9/16/2010):请参见我发布的包含解决方案的答案。