我有一个程序能够从socket接收数据,进行质量控制和其他条件处理,然后将其写入命名管道。我对它运行了valgrind并修复了原本存在的所有内存泄漏。然后我在一个系统上创建了一个“演示”环境,其中有32个实例运行该程序,每个实例都被提供唯一的数据并输出到自己的管道。我们进行了测试,一切看起来都很好。然后我试图通过增加发送数据的速率来进行压力测试,最初情况看起来不错...但我的程序持续消耗更多的内存直到没有资源可用。
我转向valgrind,并使用leak-check=full在每个程序内部运行相同的设置。发生了一些奇怪的事情。首先,内存确实泄漏了,但只到每个程序已经消耗了我的内存的0.9%(以前最大的内存占用量为6%)。使用valgrind时,程序的CPU成本飙升,我的CPU利用率达到了100%,负载平均值很高,因此可能是可用CPU不足导致程序运行缓慢,使泄漏需要太长时间才能显现。当我尝试停止这些程序时,valgrind并没有显示任何直接的内存泄漏,它显示了一些潜在的内存泄漏,但我检查过它们并不认为它们代表实际的内存泄漏;而且可能的内存泄漏只显示为几KB,而程序却消耗了超过100MB。valgrind报告的可达(未泄露)内存也是在KB范围内,因此valgrind似乎认为我的程序消耗的内存只是Top所显示的使用量的一小部分。
我进行了一些其他测试,并得到了奇怪的结果。单个程序即使以原始内存泄漏被检测到的三倍速率运行,似乎也从来不会消耗超过0.9%的内存。两个程序泄漏了1.9%和1.3%的内存,但不会再多等。好像泄漏的内存量和泄漏的速率取决于同时运行我的程序实例的数量;这毫无道理,每个实例应该是完全独立的。
我还发现,如果我运行32个实例,只有一个实例在valgrind中运行,那么在valgrind之外运行的实例将泄漏内存,但速度比在valgrind中运行的实例要慢。valgrind实例仍然会说我没有直接泄漏,并且报告的内存消耗比Top所显示的要少得多。
我转向valgrind,并使用leak-check=full在每个程序内部运行相同的设置。发生了一些奇怪的事情。首先,内存确实泄漏了,但只到每个程序已经消耗了我的内存的0.9%(以前最大的内存占用量为6%)。使用valgrind时,程序的CPU成本飙升,我的CPU利用率达到了100%,负载平均值很高,因此可能是可用CPU不足导致程序运行缓慢,使泄漏需要太长时间才能显现。当我尝试停止这些程序时,valgrind并没有显示任何直接的内存泄漏,它显示了一些潜在的内存泄漏,但我检查过它们并不认为它们代表实际的内存泄漏;而且可能的内存泄漏只显示为几KB,而程序却消耗了超过100MB。valgrind报告的可达(未泄露)内存也是在KB范围内,因此valgrind似乎认为我的程序消耗的内存只是Top所显示的使用量的一小部分。
我进行了一些其他测试,并得到了奇怪的结果。单个程序即使以原始内存泄漏被检测到的三倍速率运行,似乎也从来不会消耗超过0.9%的内存。两个程序泄漏了1.9%和1.3%的内存,但不会再多等。好像泄漏的内存量和泄漏的速率取决于同时运行我的程序实例的数量;这毫无道理,每个实例应该是完全独立的。
我还发现,如果我运行32个实例,只有一个实例在valgrind中运行,那么在valgrind之外运行的实例将泄漏内存,但速度比在valgrind中运行的实例要慢。valgrind实例仍然会说我没有直接泄漏,并且报告的内存消耗比Top所显示的要少得多。
我对导致这种结果的原因感到困惑,也不知道为什么valgrind无法检测到内存泄漏。我认为可能是外部库的问题,但我实际上并没有使用任何外部库,只用了基本的C++函数/对象。我还考虑过数据写入输出管道太快,导致缓冲区无限增长。但问题在于,1)这样的缓冲区应该有一个上限;2)一旦存在内存泄漏,如果我将数据输入速率降至零,内存仍然被占用,而不是缓慢地回落到合理的水平。
有人能给我一个提示,在哪里继续寻找吗?我完全不明白为什么内存会表现出这种行为。
谢谢。