Using top

Operate as root. Open two terminal windows. In one you will run top, to watch process activity. In the other you will launch processes to watch. We'll call these the top window and the processes window. Of particular interest are cpu-heavy and memory-heavy processes. process_priority.c  is a cpu-greedy program, and memory3.c is a memory-greedy one. Obtain them per your instructor. Compile them:

gcc  process_priority.c   -o  process_priority

gcc  memory3.c   -o  memory3

process_priority wastes time by just operating a triple nested loop (that does nothing). You can calibrate it to use more or less CPU cycles by choosing a greater or lesser loop counter value. You can also set a priority, expressed as a value in the range from -20 (highest priority) to 19 (lowest priority). Linux calls this the "nice value." We want it to run long enough that we'll have time to observe its effect in top. Fifteen seconds would be reasonable, but you can control it to your taste. Run it:

./process_priority

and note the advisory message:

"Please type:
  process_priority <loop count limit> <nice value>"

Re-run it, supplying the 2 requested arguments. Use 500 for "loop counter limit" and 0 for "nice value."

./process_priority 500 0

Depending how long the program takes to complete (longer on a slower machine, shorter on a faster one), change the loop counter limit till the program lasts for an appreciable time like 10 or 20 seconds. It might be in the high hundreds for a slow machine up into the low thousands for a fast one. Raising the value a little slows down the program a lot. Interrupt the program any time with ctrl-C if it is taking too long. You can measure how long the program is taking just by noting it approximately, or by your wristwatch, or if you want to be precise you can let the computer do it:

time ./process_priority 500 0

Calibrate this thing by raising 500 to the point that "time" reports a "real" or elapsed wall time of about 15 seconds. Suppose the counter value that yields 15 seconds is 2000.

In the top window, launch top:

top

top lists all the processes in your machine. It orders them by their "share of elapsed cpu time." It refreshes the list every 3 seconds, showing resource consumption by each process during the most recent 3-second interval.

In the processes window:

./process_priority  2000  0  &

While process_priority is running top will show it, probably first in the list because process_priority is getting a large amount of cpu time. Note the value for process_priority in the column labeled %CPU. On my system, so long as process_priority is running, it's 100 or very close to it. Meantime note the row in the upper display area labeled "%Cpu(s):". On my system it shows 25 or close to it. My system has 4 cores in the processor. That's 4 cpu's as far as top is concerned. And process_priority is running on just one of them. It's using all of that one cpu's processing power, and none of the processing power of the other three. So it's using 25% of their overall combined power. Press the "1" key and a separate line will open up for each cpu in the upper display area, showing 100 for one of them and 0 for the other three, or close to it. Press the "1" key again to revert to the single-line display of fractional consumption of overall combined cpu power.

top is interactive. There are a number of other interesting keystroke toggles. Let's try some. Press the "i" key. The list is reduced to only those processes that used some cpu resource in the past 3 seconds. Those that didn't are banished from the display. "i" stands for "idle," toggling the display of idle processes off and on.

Press the "s" key and when prompted, give 0.5 as the delay interval. top now refreshes at half-second intervals instead of 3-second.

top itself, as a process, consumes resources and shows up in the list. Note the %CPU values shown for it. Use "s" again to set the interval to 0. This will make top busy all the time. Try to read top's %CPU value from the fast-moving display if you can. Then set the interval back to 3.

Use the "i" idle toggle to make sure idle processes are being shown (i.e., that the list is long and un-truncated). Press the "x" key. The values in the %CPU column are bold-highlighted. That shows that this is the column on whose value the list is being sorted. If unsure at any given time how the list is being sorted, this tells you.

Let's change it to sort on memory consumption. Press the "f" key. In the resulting screen, arrow to "%MEM" then press "s" followed by "q". When the top list is back on the screen, press "x" again to highlight the sort column. It is now %MEM instead of %CPU. In the process window, in order to consume some memory, run memory3.

./memory3

memory3 endlessly asks the operating system to allocate more memory to it, until it has all or nearly all of RAM. RAM is now exhausted. memory3 keeps asking for more, and the operating system gives it swap until that too is exhausted. At that point the operating system gracefully terminates memory3. Along the way however, some degree of memory starvation affects most processes and you may see top stutter, unable to keep its paced interval, and your shell or desktop/mouse may become lethargic or unresponsive. 

While memory3 is eating up all the memory in sight, observe both the %MEM value shown for it, and the global memory consumption statistics shown in the upper summary area, as the amounts "used" rise higher and higher. Ultimately when the operating system kills memory3 the "used" amount falls back and the "free" amount goes back up to something reasonable as the RAM that was in memory3's possession is deallocated/recovered. Set top back to %CPU sort instead of %MEM sort, using the "f" key again.

Show a filtered list of processes. Suppose you only want to see the currently running instances of bash. Press the "o" key, then "COMMAND=bash". It does a substring search for "bash" within the COMMAND column. Press the "=" key to undo the filter. Maybe you want to see realtime processes (if any). Press "o" and give PR=rt. Then "=" to undo.

top (like ps) can show you more information fields than fit on the screen. So there is the user capability of choosing which ones to display. By default it shows you 12 fields/columns. If you want to include another one, you can again use the "f" key and select it for display from the resulting list (read the prompts on the screen for how to do it). The 12 fields that top shows by default are a particular subset of all that are available. top has 3 other particular subsets, called field groups. Switch to field group 2 with the "g" key. Then to field group 3, then 4. "Alternate display" shows all 4 field groups by sharing the screen among them. Press the "A" key. Each of the 4 field groups gets its own "window." One of them is the "current window." That means it's the window to which all commands are directed, and whose information is shown in the summary area. Because you were showing group 4 just before invoking alternate display, it's now named in the summary area's upper left corner, telling you that 4's window is the current one. Try the "x" key to highlight the current sort column, and you will see it affects one of the columns in window 4, but not the other windows. Use the "g" key to switch to another window. Use the "x" key again and note it is directed to the new current window you chose. Make window 1 current, then press the "A" key to toggle out of alternate display mode and back to normal.


There is a fundamental difference between two similarly named quantities in top's output: $Cpu(s) in the summary area, and the %CPU field per process. 

%Cpu(s) is processor-centric, about utilization of the processor(s). It shows, either individually for each cpu or for all of them as a group, what kinds of activities they spent their time doing. There are 8 kinds of activities. The main ones are:

 - executing user code
 - executing system/kernel code
 - sitting idle

top shows the percentage distribution of the processor's (or processors') time spent on each. The numbers must add up to 100. For example, the processor(s) could spend 1% of the time in user code, 1% in system code, and 98% idle. Or if running a demanding process perhaps 97% in user code, 2.5% in system code, and 0.5% idle. These numbers are taken over top's most recent 3-second (or other) measurement/refresh interval. Every 3 seconds they change, because they are talking about the distribution of activities over a different period, hence it's not the same distribution.

%CPU by contrast is process-centric. It is not about utilization of cpus. It's about the experience of a process in vying for cpu attention and how much of the time it got it. Consider processes to be selfish: each wants an entire cpu to itself at all times. If there are 4 processors and 4 processes, that's enough to go around 1-to-1 so that each process gets its wish. But if there are 8 processes then they have to double up and share, two to a processor. Each gets only 50% of a full-processor's-worth of time. %CPU will show 50 (or 1/2). If there were 16 such processes they would share 4-per-processor and each would show 25 (or 1/4). If there were 24 procceses they would share 6 to a processor and show 16.7 (or 1/6).

Let's see it happen. Determine how many processors/cores are in your machine. Some commands that may be installed on your machine can indicate how many cores you have and other information about your CPU:

nproc
lscpu
more  /proc/cpuinfo

Now you will run multiple instances of process_priority. While doing so scrutinize the %Cpu(s) information for the processors, shown in the summary area; and also the %CPU field for each of the process_priority instances. First, caclulate half the number of processors that your computer has, and run that many instances of process_priority. If you have four processors, you want to run 2 processes. Let the computer do the arithmetic. In the processes window:

n=$[ $(nproc)/2 ]
echo $n
for  i  in  $(seq 1 $n);  do ( ./process_priority  2000  0  >  /dev/null  & );  done

Hint: if at any time you are finished studying on-screen results and don't want to wait for the processes to terminate naturally you can kill them with killall  process_priority

While this is ongoing toggle the "1" key to see processes represeneted both individually, and together. Now run an equal number of processes as processors:

n=$(nproc)
echo $n
for  i  in  $(seq 1 $n);  do ( ./process_priority  2000  0  >  /dev/null  & );  done

All the statistics show 100%. But now run one more process than there are processors, and watch the $Cpu statistics remain at 100% (because the processors remain fully occupied, and then some) while the per-process %CPU statistics slip down from 100% (because there are other processes with which they must now share, and are no longer able to get an entire cpu unto each):

n=$[ $(nproc)+1 ]
echo $n
for  i  in  $(seq 1 $n);  do ( ./process_priority  2000  0  >  /dev/null  & );  done

Now run numbers of processes that are multiples of the number of processors. Like, twice as many processes as processors, or 5 times as many, or 7 times as many. If you run n times as many processes as processors you should see the %CPU fields show 1/n as a percentage. If you run 7 times as many, you should see about 14% (or 1/7) in those fields:

n=$[ 7*$(nproc) ]
echn
for  i  in  $(seq 1 $n);  do ( ./process_priority  2000  0  >  /dev/null  & );  done

This introduction to top gives you a taste of the tool, what it does, and some of its more important features. Top is rich in features. For those, go to the man page. You can have fun with its section 7, "Stupid tricks sampler".

 

Look briefly at htop. It's a graphical top. Install htop:

dnf  install  htop

Run it from the command prompt (and don't put it in the background-- no trailing ampersand please):

htop

Observe the keystroke commands along the bottom and play with a few of them. Here is a website featuring htop and a few interesting things you can do with it.

------------
for reference, from top's man page

       Line 2 shows CPU state percentages based on the interval since the
       last refresh.

       As a default, percentages for these individual categories are
       displayed.  Where two labels are shown below, those for more recent
       kernel versions are shown first.
           us, user    : time running un-niced user processes
           sy, system  : time running kernel processes
           ni, nice    : time running niced user processes
           id, idle    : time spent in the kernel idle handler
           wa, IO-wait : time waiting for I/O completion
           hi : time spent servicing hardware interrupts
           si : time spent servicing software interrupts
           st : time stolen from this vm by the hypervisor

 

        1. %CPU  --  CPU Usage
           The task's share of the elapsed CPU time since the last screen
           update, expressed as a percentage of total CPU time.

           In a true SMP environment, if a process is multi-threaded and top
           is not operating in Threads mode, amounts greater than 100% may
           be reported.  You toggle Threads mode with the `H' interactive
           command.

           Also for multi-processor environments, if Irix mode is Off, top
           will operate in Solaris mode where a task's cpu usage will be
           divided by the total number of CPUs.  You toggle Irix/Solaris
           modes with the `I' interactive command.