简体   繁体   English

内存泄漏测试和常量变量

[英]Memory leak testing and constant variables

I'm working on tests to detect memory leaks for classes.我正在测试以检测类的内存泄漏。 I do this with the following pattern:我使用以下模式执行此操作:

  • Get initial memory in test setup (using GC.GetTotalMemory(true) )在测试设置中获取初始内存(使用GC.GetTotalMemory(true)
  • Perform operations, such as instantiation of objects执行操作,例如对象的实例化
  • Dispose object (through useage block)处置对象(通过useage块)
  • Get memory in test tear down (using the same method again, all objects are out of scope and therefore should be garbage collected)在测试拆卸中获取内存(再次使用相同的方法,所有对象都超出范围,因此应进行垃圾回收)
  • Ideally, assert that the different between initial and end memory = 0理想情况下,断言初始和结束内存之间的差异 = 0

Using memory profiling tools in my tests, I see that const string (and related) declarations are counted towards the leaked memory for a test.在我的测试中使用内存分析工具,我看到 const 字符串(和相关)声明被计入测试的泄漏内存。 I'd like these values to be already declared when doing the initial memory measurement, such that they do not generate a 'leak' that is detected by the test.我希望在进行初始内存测量时已经声明了这些值,这样它们就不会产生测试检测到的“泄漏”。 However, I don't want to run the action code twice, because that would prevent me from detecting leakage of variables in static variables (like not having cleaned up singleton pattern object that should not have application life-time).但是,我不想两次运行操作代码,因为这会阻止我检测静态变量中变量的泄漏(例如没有清理不应该具有应用程序生命周期的单例模式对象)。

Is there a way to do this?有没有办法做到这一点? Do I have to do a manual compensation for these variables per test case (which has the drawback of having to be actively maintained, which will probably won't happen in the long run)?我是否必须为每个测试用例对这些变量进行手动补偿(其缺点是必须积极维护,从长远来看可能不会发生)? Is there a moment in runtime which I can use for this purpose?是否有运行时的某个时刻可以用于此目的? Or will I have to just accept that I cannot test for a memory leak near 0 bytes?或者我将不得不接受我无法测试接近 0 字节的内存泄漏?

(For those interested: I'm already using WeakReferences and livelyness checks to monitor if objects that I instantiate in the test are properly garbage collected, but this won't cover private state that leaks) (对于那些感兴趣的人:我已经在使用 Wea​​kReferences 和 livelyness 检查来监视我在测试中实例化的对象是否被正确垃圾收集,但这不会涵盖泄漏的私有状态)

It's more or less futile trying to find small memory leaks in managed memory.试图在托管内存中找到小的内存泄漏或多或少是徒劳的。 Instead, if possible, try a much bigger scope - allocate the objects 100 000 times, and see if there's a significant difference on cleanup.相反,如果可能,尝试更大的范围 - 分配对象 100 000 次,然后查看清理是否有显着差异。

In practice, you probably want to do something completely different, though.但实际上,您可能想做一些完全不同的事情。 Amount of memory is generally not a very reliable check for managed leaks.内存量通常不是对托管泄漏的非常可靠的检查。 Instead, you might want to let your application run over and over in a cycle, and use eg the CLRProfiler to see the lifetime of objects.相反,您可能希望让您的应用程序在一个循环中一遍又一遍地运行,并使用例如 CLRProfiler 来查看对象的生命周期 If there's something suspicious that hangs on for minutes or even hours, that's probably a leak.如果有可疑的东西持续数分钟甚至数小时,那可能是泄漏。 This gives you a much better idea than just checking memory size.这比仅检查内存大小为您提供了一个更好的主意。

Of course, in general, you shouldn't really care.当然,一般来说,你不应该真正关心。 There's very little benefit in hunting a memory leak until it actually hurts you.寻找内存泄漏直到它真正伤害到您为止几乎没有什么好处。 Do note that I'm talking only about managed memory.难道请注意,我谈论管理的内存。 Any place where you're not using managed memory only should be given significant attention - whether it's native code, unsafe pointers or any other form of an unmanaged handle.任何不只使用托管内存的地方都应该得到极大的关注——无论是本机代码、不安全的指针还是任何其他形式的非托管句柄。 Do note that this includes networking code (sockets have unmanaged memory), file operations (file handles), some synchronization primitives (wait handles), image data (most notably GDI+'s Bitmap class, WPF is full of these as well) and more.请注意,这包括网络代码(套接字具有非托管内存)、文件操作(文件句柄)、一些同步原语(等待句柄)、图像数据(最著名的是 GDI+ 的Bitmap类,WPF 也包含这些)等等。 Generally, though, using high-level approaches, you can usually safely ignore most issues until they actually noticeably manifest under realistic conditions.不过,一般而言,使用高级方法,您通常可以安全地忽略大多数问题,直到它们在现实条件下真正明显地显现出来。

Now, all that said, your methodology is suspect anyway.现在,综上所述,无论如何,您的方法是可疑的。 You have to force the GC to run (using the current implementation, it will only collect based on memory pressure, not because you left scope - and stack is quite a separate issue as far as GCing is concerned).您必须强制 GC 运行(使用当前的实现,它只会根据内存压力进行收集,而不是因为您离开了范围 - 就 GC 而言,堆栈是一个相当独立的问题)。 The usual practice to force a full GC is like this:强制执行完整 GC 的通常做法是这样的:

  1. GC.Collect(); GC.Collect();
  2. GC.WaitForPendingFinalizers(); GC.WaitForPendingFinalizers();
  3. GC.Collect(); GC.Collect();

The whole process then needs you to first warm everything up, ie.整个过程然后需要您首先预热所有东西,即。 do one complete cycle of the test first.首先做一个完整的测试周期。 Then you do a full forced GC as noted above.然后你做一个完整的强制 GC,如上所述。 Then you do (say) a thousand cycles of the test.然后你做(比如)一千个循环的测试。 And after that, you do another full GC.之后,您再进行一次完整的 GC。 This should give you a much clearer picture of real memory usage.这应该可以让您更清楚地了解实际内存使用情况。

Static field memory leaks are only interesting if they're either working with a lot of memory (in which case, you should simply ask why the hell is this using so much memory, and what can I do about it? ), or if they increase over multiple calls or over time (in which case, this methodology will still let you discover the issue).静态字段内存泄漏仅在它们处理大量内存时才有意义(在这种情况下,您应该简单地问一下为什么使用这么多内存,我该怎么办? ),或者如果它们多次调用或随着时间的推移而增加(在这种情况下,此方法仍可让您发现问题)。

Also, what do you mean, a singleton object that does not have the scope of the application?另外,你是什么意思,一个没有应用范围的单例对象? If that's what you need, you really, really shouldn't be using a singleton!如果这就是你所需要的,你真的,真的不应该使用单例! You have very little control over when the singleton is created or destroyed, and you can't recreate it after it has been destroyed.您几乎无法控制何时创建或销毁单例,并且您无法它被销毁重新创建它。 And of course, most people will probably tell you not to use singletons at all nowadays - one of the reasons being the fact that unless they have no state, they more or less kill any chance of using practices such as unit testing.当然,现在大多数人可能会告诉你根本不要使用单例——原因之一是,除非他们没有状态,否则他们或多或少会扼杀任何使用单元测试等实践的机会。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM