I have a service and I need to make sure that it doesn’t have a memory leak after running for a sustained length of time. I’m doing all the good stuff in code to manage the garbage collection and I have the right tools to check for leaks in my code. But I still want to monitor an instance of the service during regular usage. I don’t need anything too finely grained, I just want to see if the memory usage is trending upwards. There’s a good chance that I might have to deploy this out in the field, so I want something simple. I could have used the Performance console, but I wanted something very simple to explain. You can probably do this with a CScript batch file and WMI, but I wanted something fast to load and fast to exit.
What I want is to log the memory usage to a text file, with each entry timestamped. I was able to do this with almost all off the shelf parts. I did have to write the timestamper, but that was a trivial task. Since the home viewers will not have my service, pick a service or app of your own and play along. I’ll describe what I did using FireFox as a substitute for the actual service.
In the excellent PsTools suite over at SysInternals site, there is a utility named PsList. It’s a combination of the pmon and pstat tools that works like a command line version of the “Processes” tab of Task Manager. By default it lists information for all running processes, but you can filter it by service name or process ID. I wrote a batch file to call PsList with the service name and the “-m” command line switch to print the memory usage. PsList prints some banner information with the details. Something like this:
PsList 1.26 - Process Information Lister
Copyright (C) 1999-2004 Mark Russinovich
Sysinternals - www.sysinternals.com
Process memory detail for Kremvax:
Name Pid VM WS Priv Priv Pk Faults NonP Page
firefox 3936 108952 41380 32748 36452 140201 8 54
All fine and good, but not pretty enough for a log file. What I need was just the last line. So I piped the output from PsList through the good ‘ol FIND command with “firefox” as the filter text. With that, I can redirect the output to a file (with append). I ended up creating a batch file named memlog.cmd that had the following commands:
pslist -m firefox | find "firefox" >>c:\logs\memuse.txt
That gave me the last line in a file. But I still needed the time stamp. I thought about going through some script file sleight of hand with ECHO and DATE, but this is the Windows Server 2003 CMD.EXE. It doesn’t have that skill set. I could do with some 3rd party shells, but the goal is something I can deploy on a remote site without anyone having to pay for a tool or go through the hassle of installing something like Power Shell.
Time to fire up Delphi and create a little command line app that would take text coming in as standard input and send it back out as standart output, but with a timestamp prepended to the text. The source code has less text in it than the previous sentence. If you have Delphi, the following code will give you that mini-tool. I used Delphi 7, any of the Win32 versions should do.
program dtEcho;
{$APPTYPE CONSOLE}
uses
SysUtils;
var
s: string;
begin
ReadLn(s);
WriteLn('[' + FormatDateTime('yyyy-mm-dd hh:mm', Now) + '] ' + s);
end.
There’s no banner or error checking. I didn’t need any of that and I wanted to keep it light. By adding dtEcho to my batch file like this:
pslist -m firefox | find "firefox" | dtecho >>c:\logs\memuse.txt
I now get output like this:
[2006-07-28 23:14] firefox 3936 536904 61324 51244 57384 445377 90 249
[2006-07-28 23:15] firefox 3936 538176 60844 50764 57384 449193 91 249
[2006-07-28 23:16] firefox 3936 538212 60620 50528 57384 455935 91 249
The output only goes down to the minute, I’m tracking the memory usage every 10 minutes, I didn’t need to make the timestamp that granular. If I needed it, I just need to make a slight change the dtEcho source code and it will print the seconds.
To run that batch file, I just used the scheduled tasks control panel applet and set it to run off of my account. For remote deployment, that would probably be the hardest step.