Tech —

Mac OS X 10.1

Memory diagnostics

There are several tools for measuring RAM usage included with Mac OS X. Unfortunately, most of them are command line programs. (A comprehensive GUI memory monitor would be a nice addition to Mac OS X 10.2.) There's not even an equivalent of the basic per-application memory usage graph provided in classic Mac OS's "About this Mac" dialog. Of course, such a simple summary is not possible in Mac OS X due to the vast differences between its memory management and classic Mac OS's.

The most basic memory diagnostic tool is the vm_stat program. The output looks like this:

% vm_stat
Mach Virtual Memory Statistics: (page size of 4096 bytes)
Pages free:                    24350.
Pages active:                  30419.
Pages inactive:               121158.
Pages wired down:              20681.
"Translation faults":      334217454.
Pages copy-on-write:         1129146.
Pages zero filled:          98430493.
Pages reactivated:            456481.
Pageins:                      199957.
Pageouts:                     121833.
Object cache: 363343 hits of 760464 lookups (47% hit rate)

(That's from my very busy G4; can you tell?) Most of those items should make sense to you after the earlier explanation: pageins, pageouts, pages wired down, etc. The "pages active/inactive" lines reflect the OS's distinction between pages that it currently considers eligible to be swapped out, and pages that it considers "active." The other numbers are less interesting, and are explained in the vm_stat manual page, available by typing "man vm_stat" at the command line. (In particular, do not be concerned with the scary looking "Translation faults" line.)

The top command provides a slightly more sophisticated picture of memory usage. top is useful for more than just memory diagnostics. Its purpose is to show the most demanding processes currently running—the "top" (usually 15) processes, so to speak. CPU usage is a big a factor in determining the order of the top processes, but top's output also includes information about each process's memory usage, as well as an overall memory usage summary. Here's my otherwise idle G4, as seen from a terminal window at home:

Processes:  56 total, 2 running, 54 sleeping... 149 threads        12:55:32
Load Avg:  0.09, 0.00, 0.00     CPU usage:  5.1% user, 8.5% sys, 86.3% idle
SharedLibs: num =  132, resident = 24.3M code, 1.87M data, 5.85M LinkEdit
MemRegions: num = 5485, resident =  140M + 8.62M private,  170M shared
PhysMem:  80.8M wired,  119M active,  474M inactive,  673M used, 94.8M free
VM: 3.06G + 56.2M   199957(0) pageins, 121833(0) pageouts

29269 top         13.7%  0:00.56   1    15    15   312K   324K   552K  1.45M
29257 tcsh         0.0%  0:00.24   1    24    16   500K   652K   960K  5.97M
29256 telnetd      0.0%  0:00.07   1    23    13    76K   332K   288K  1.30M
29159 ScreenSave   0.0%  2:34.32   3    85   589  10.4M  23.6M  26.9M  93.9M
29156 telnet       0.0%  0:00.17   1    16    15    88K   368K   328K  1.46M
29132 ASM Contro   0.0%  0:00.14   1    49    27   568K   588K  1.39M  34.1M
29131 System Pre   0.0%  0:03.18   2    66   106  2.61M  8.67M  5.98M  69.6M
29130 SystemUISe   0.0%  4:38.49   2    95   137  3.40M  7.33M  4.82M  70.4M
25353 Interarchy   1.7% 54:52.03   8   129   159  5.88M  38.1M  20.2M   117M
25348 DragThing    0.8%  7:59.17   1    55   115  2.73M  9.49M  3.91M  65.7M
25347 Fire         0.0%  2:20.39   3   113   166  3.02M  8.17M  5.42M  70.4M
25339 SecurityAg   0.0%  0:00.47   1    63    74   892K  7.65M  2.74M  65.9M
25312 BBEdit       0.0% 13:31.95   5   117   183  7.15M  70.9M  66.2M-  204M
25310 telnet       0.0%  0:00.23   1    16    15    92K   368K   324K  1.46M
25309 telnet       0.0%  0:00.49   1    16    15    92K   368K   324K  1.46M

A detailed description of the fields is in the lower portion of the output is available in the top manual page (type "man top" at the command line). Unfortunately, the summary information at the top of the output is not explained in the manual page. Fortunately, most of it is either self-explanatory (total number of processes and threads) or esoteric (number of memory regions).

The most interesting memory information in the summary section is in the bottom two lines. Like vm_stat, they list the amount of used, free, "wired down," "active," and "inactive" memory, but in more friendly units of megabytes (instead of vm_stat's very large numbers displayed in pages).

Don't be too concerned with the "free" memory statistic. During moderate to heavy usage, this will probably converge on a constant of a few megabytes. The number(s) you do want to look at to gauge memory usage as it relates to performance are described next.

The pagein/pageouts lines list two numbers (e.g. "199957(0)" for "pageins" above). The first number is the cumulative number of pageins or pageouts since the system was rebooted. The second number (in parenthesis) is the number of pageins or pageouts that have occurred in the last second. If those numbers in parenthesis stay above zero for a sustained period of time, that's an indication that you could use a bit more RAM. If they stay at, say, 50, or more for a sustained period of time, that's a sign that your system is thrashing. (Of course, you probably won't need top to tell you that if you're at the computer and can hear the drives yourself.)

The lower portion of top's output lists information about the top 15 (in this case) processes on the system. The last four columns contain memory usage information. The most important is the RPRVT column, which stands for "Resident Private." It shows the amount of physical RAM that is currently allocated for the private use of each process. (For all you long-time Mac users, this is the closest analog to the "filled" portion of the memory usage bars in classic Mac OS's "About this Mac" dialog.) RPRVT is a reasonable indication of the "working set" of each process.

The RSHRD column shows the amount of resident physical memory a process is sharing with one or more other processes. RSIZE shows the total amount of physical memory used by an application, including memory shared with other processes. (It may seem like this number should be the sum of RPRVT and RSHRD, but that's not the case. I suspect this is because RSHRD includes the total number of resident pages for each shared library, rather than just the resident pages that a particular application is using. Can anyone shed some light on this?)

Finally, the VSIZE column shows the total amount of (virtual) memory each process has allocated. This number is often very large. But remember, the amount of resident physical memory (e.g. RSIZE) is much more important.

The memory used for each application's window buffers is somewhat misleadingly lumped into the RSHRD column because it is shared with the window server process. BBEdit, for example, shows an RSHRD size of 70.9M, most of which is due to window buffers. The window server process itself is not in the top 15 (not surprising, since I'm connected via the Terminal right now and no one is using the GUI), but the "-l" option to top will list all processes. The (trimmed) output below shows that the window server is using a total of 124M of physical RAM (120MB of which is listed under RSHRD because the window buffers are shared with the corresponding applications). The total virtual memory size is a whopping 203M.

% top -l1
25283 Finder       0.0%  1:50.01   2    89   551  29.2M  15.9M  31.8M   103M
25278 pbs          0.0%  0:04.28   1    31    32  2.50M   696K  3.19M  19.9M
25269 loginwindo   0.0%  0:04.87   8   152   172  3.82M  7.97M  6.46M  71.9M
25268 Window Man   0.0% 76:48.92   4   249   279  3.91M   120M   124M   203M
13929 httpd        0.0%  0:00.01   1     9   168     0K   300K    72K  3.34M
13928 httpd        0.0%  0:00.01   1     9   168     0K   300K    72K  3.34M

One final diagnostic tool is useful for getting information about a particular process. The first column of top shows the PID or "process identifier." The ps command can be used to get information about a particular process using this number. For example:

% ps -o'pid,command,rss,rsz,vsz' -p 25268
25268 126520 126520   207468 /System/Library/CoreServices/WindowServer console

The ps command has a bewildering array of options, but the example above should be fairly self-explanatory at this point. I'll leave further investigation as an exercise for the reader. (Hint: "man ps")

Memory Usage Summary

As should be clear by now, OS X loves RAM. The OS and the applications themselves need some, of course, but it's the "extra" consumers like the window server and the buffer cache that really put OS X in a league of its own. OS X's virtual memory system does an admirable job of keeping the physical RAM where it will do the most good, but there's nothing it can do when the working set far exceeds the available physical RAM—as is often the case on a busy system with many open applications, windows, and files, and a "Mac OS 9 caliber" complement of RAM.

RAM is already relatively inexpensive, and it will only get cheaper. If you are serious about using OS X on your current system, and you currently have less than 512MB or RAM, you should consider upgrading. (No, I'm not getting kick-backs from RAM vendors for this recommendation. But maybe I should ;-)

Mac OS X 10.1's RAM usage behavior has not been substantially different than 10.0, in my experience. Some applications that were revised for 10.1 take more RAM than their 10.0.x counterparts, and some take less (as we'll see in a bit). But the biggest factors in RAM usage—the memory architecture, buffer cache, and window server—remain unchanged in 10.1. Mac OS X 10.0.x needed a lot fo RAM to operate smoothly, and so does 10.1. I know this was a heck of a long section for such an unexciting outcome, but I hope that it's been informative for at least some readers.

You must to comment.

Channel Ars Technica