views:

72

answers:

1

So I'm trying demonstrate to my uppers that the product contains a memory leak. However, it takes about 2 hours of running a script that touches a COM object to duplicate up to an OutOfMemoryException. In order to make this presentable, I'll need data for a baseline to show that it's not my script itself that's causing the memory problems, as well as the data to show that the behavior indeed duplicates a memory leak.

I plan to do this via a periodic report of total memory usage pooped out into a log file. For example, on this box I my Windows Task Manager -> Performance tab shows that I'm currently using 1.67GB out of 2.00GB. That's the number I need to pull into my code and dump in a log file periodically.

Only one problem... how do I get that piece of information?

Thanks for any help you can provide, even if it's to tell me it's impossible :P.

UPDATE: Thanks for the info on COM's memory issues, but the "baseline" of which I spake also touches the COM object in effectively identical ways and doesn't cause memory issues on the order of magnitude that a specific behavior does. Only answers to the question I posed would be helpful to me here.

+1  A: 

Update:, In answer to the OP's question, class System.GC has a method for getting an estimate of the amount of memory in use:

System.GC.GetTotalMemory(false)

If you are using COM on a long-running process (i.e. no idle time) then you will experience a memory leak unless you periodically call:

Thread.CurrentThread.Join(100);

The 100 can of course be changed, but will be how long your active thread "sleeps" before resuming. From the docs:

Blocks the calling thread until a thread terminates or the specified time elapses, while continuing to perform standard COM and SendMessage pumping.

It is that last clause that is key.

Reference: http://support.microsoft.com/kb/828988

If a console application that is based on a single-threaded apartment (STA) creates and then uses STA Component Object Model (COM) components and the console application does not perform sufficient operations to pump COM messages, such as calling the Monitor.Enter method, the Thread.Join method, and others, the following symptoms may occur. Also, if the console application performs operations that that run for a long time and that do not pump messages, such as calling the Console.ReadLine method, the following symptoms may occur:

  • The release of COM components may be delayed.
  • The calls to the Finalize methods of the objects that the garbage collector collects may be delayed.
  • Calls to COM components may block the application thread for extended periods. The memory amount that the STA application process uses may increase over time.
  • Calls to the GC.WaitForPendingFinalizers method may take a long time to return.
Kirk Woll
Do you have a reference for that? Why should simply be using COM lead to a memory leak?
0xA3
@0xA3, I experienced this bug on a windows service I wrote to perform a long-running task using WatiN (which uses IE as a COM component). Not until I added this line between iterations did the leak go away. COM components need to be able to "pump events" or they can't clean up after themselves. It's like not having a GC. I'll see if I can dig up the link that steered me in the correct direction.
Kirk Woll
@0xA3, ah, there it is. Edited answer to include.
Kirk Woll
Thanks a lot, Kirk! That was really useful information, I didn't know about that.
0xA3
@0xA3, yeah, caught me completely by surprise too. Just goes to show that when you step out of the CLR it's a wilderness out there. ;)
Kirk Woll
Thanks for the info Kirk. This is very useful to know. However, it doesn't answer the question I posed.
Legatou
@Legatou, I updated my answer to show how to obtain a count of the allocated memory.
Kirk Woll
@Kirk, so very, very close to what I want. I'm not quite looking for the amount of memory allocated by my program, but all memory used by the system. For example, on this box I my Windows Task Manager -> Performance shows that I'm currently using 1.67GB out of 2.00GB. That's the number I need to pull into my code and dump in a log file periodically somehow.
Legatou