Windows XP slowdown, what's to blame?

I run Windows XP and after a while it seems to get real sluggish. I suspect it's heavy memory consumption of Firefox, but have noticed several other programs are 'slow' to exit when I reboot.

Is there a way to measure all process memory consumption over time? Process explorer is what I want, but for every process, not just the one I open properties for.

In Unix-land, I'd run ps snapshots repeatedly, and look at RSS (and blatantly ignoring shared memory pages) calculate what

  • is being a pig right now
  • grew the most (while I was not looking).

I need about 8-24 hours of history per process, not just what can fit on the screen.

Any ideas?


Solution 1:

Some time ago I wrote Windows Perfmon: The Top Ten Counters at my old blog. The article is a quick introduction to using Perfmon to determine where hardware bottlenecks are: processor, memory, disk, or network (and secondarily, to determine current operational loads on these resources). I can't emphasize this step enough: first make sure you know which hardware resource is overused. Then go hunting the resource hog.

Once you've determined which resource is overused, you have two choices: add more of that resource (get a faster CPU, add memory, get a faster disk or NIC) ... or track down the top users of that resource, and either kill them or take steps to make them less piggish.

The easiest way to track down top resource hogs is with Process Explorer. Be sure to run it from an account with Admin privs. Here's a quick-and-dirty list of things to look for:

  • For memory bottlenecks (the most common bottleneck), use the Working Set, Virtual Size, and Private Bytes History columns from the Process Memory tab. Sort the columns one by one, descending (largest values at top of column). Of these, Working Set is usually the most valuable.
  • For CPU bottlenecks, obviously you want the CPU Usage column. CPU History is also handy. These are on the Process Performance tab. Again sort descending. This value tends to jump around a lot more than memory usage values do, so don't make snap judgments. Watch it awhile to see if your prime suspect stays at the top for more than a few seconds.
  • For disk bottlenecks (which are often actually memory bottlenecks as the system is forced to page stuff from disk far too often) you don't really have great choices, because Windows doesn't have per-process disk I/O perfmon counters. However you can look at total I/O per process (which includes disk, network, and device I/O) you can use the I/O Read Bytes and I/O Write Bytes counters as a rough estimation. These are on the Process Performance tab.
  • Network bottlenecks are unlikely to be your issue, but since per-process network counters are lumped into I/O, you can get a rough idea in the same way I described above for disk bottlenecks. It's up to you to determine whether the I/Os you see in these columns are more likely to be disk or network I/Os. If you were on Vista/2008/7 you'd get a little help here from the Windows Performance Tools which I discuss on my newer blog.

Good luck!

Solution 2:

There's perfmon.msc and there sysInternals' Process Monitor, which logs.

Solution 3:

You may want to start by using the Task Manager, which will give you a fair bit of information.

Solution 4:

A robust alternative to the built-in Task Manager (taskmgr.exe) is Process Explorer (procexp.exe). Process Explorer was created by SysInternals and is now owned and distributed by Microsoft.

As for taking samples of your normally healthy system at regular intervals to establish baseline numbers, you could create a scheduled task that uses the PowerShell Cmdlet Get-Process, or a batch file which would use the plain-old-DOS tasklist.exe.

Solution 5:

you could use ps from sysinternals or ps from cygwin or if you know a developer it is trivial to write a program to run through every process and extract certain statistics.

This code should really be on stackoverflow and the overlords may say something but gives you an idea of how easy this task may be:

public static string ListAllApplications()
{
    StringBuilder sb = new StringBuilder();

    foreach (Process p in Process.GetProcesses("."))
    {
        try
        {
            if (p.MainWindowTitle.Length > 0)
            {
                sb.Append("Window Title:\t" +
                    p.MainWindowTitle.ToString()
                    + Environment.NewLine);

                sb.Append("Process Name:\t" +
                    p.ProcessName.ToString()
                    + Environment.NewLine);

                sb.Append("Window Handle:\t" +
                    p.MainWindowHandle.ToString()
                    + Environment.NewLine);

                sb.Append("Memory Allocation:\t" +
                    p.PrivateMemorySize64.ToString()
                    + Environment.NewLine);

                sb.Append(Environment.NewLine);
            }
        }
        catch { }
    }

    return sb.ToString();
}