swap problem: not freeing pages ?!

Harald Koenig (koenig@tat.physik.uni-tuebingen.de)
Sat, 15 Jun 1996 18:11:42 +0200 (MET DST)


running Linux-2.0.0 on ALPHA I found a problem with swapping which
also shows up (but not that severe?) for i386 (also 2.0.0):

trying to allocate as much memory (real ram) as possible and using it
by writing to every page over and over again I found that a lot of memory
doesn't get swapped out and thus is not available for a process needing
more memory:-(
for this test I'm using the "eatmem" program below e.g. like "eatmem 48000 loop".
numerical examples about the impact for alpha and i386:

ALPHA: 48MB memory, 45840k available according to "free"

I'm not able to get more than ~34.5MB memory without running into
continous swapping. summing up all the "RSS" fields in "ps axm" output
I only get ~36.5MB (note that procps-0.99a gives wrong memory sizes due to
8k page AXP size for alpha vs. 4k pages for i386; I'm using a fixed "ps"!
patch below).

after killing the memory trashing process and running "swapoff -a ; swapon -a"
and summing up the RSS for "ps axm" (not counting the "eatmem" process in
both cases for comparision now) the sum is ~10MB larger!
this is just about the amount of memory which can't be used by the "eatmem"
process when trying to use as much memory as possible.

i386: 32MB memory, 30720k available according to "free"

I'm not able to get more than 25MB memory without running into
continous swapping. summing up all the "RSS" fields in "ps axm" output
I only get 26MB.

after killing the memory trashing process and running "swapoff -a ; swapon -a"
and summing up the RSS for "ps axm" the sum is 2MB larger.
this difference is not as big as for AXP but it's still nasty.
why can't I get hands on more than 25MB memory (with 30MB available)
when only one process is running and needing (much) more memory ?

any ideas what's wrong? or where am I missing the 10MB for Linux/AXP
with no other process trying to get CPU time and thus no process trying
to compete for memory ?

Harald

-------------------------------------------------------------------------------
/*
* eatmem.c -- allocate a junk of memory and make it dirty
* Copyright Harald Koenig <koenig@tat.physik.uni-tuebingen.de> 1994
*
* Permission is hereby granted to copy, modify and redistribute this code
* in terms of the GNU Library General Public License, Version 2 or later,
* at your option.
*
* to compile use
* cc -O2 -Wall -fomit-frame-pointer -s -o eatmem eatmem.c
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <malloc.h>

void main(int argc, char *argv[])
{
int i;
char *b=NULL,*pb;
int n=(-1);
int err=0, exit_flag=0, loop_flag=0;

if (argc >= 2) {
n = atoi(argv[1]);
if (argc == 3) {
if (!strcmp(argv[2],"pause")) exit_flag = 0;
else if (!strcmp(argv[2],"exit" )) exit_flag = 1;
else if (!strcmp(argv[2],"loop" )) loop_flag = 1;
else err=1;
}
else if (argc > 3) err=1;
}
if (n<=0 || err) {
fprintf(stderr,"usage: eatmem size_in_kb [ pause | exit | loop ]\n");
exit(1);
}

b = malloc(n*1024);
if (b == NULL) {
fprintf(stderr,"malloc failed.\n");
exit(1);
}

do {
pb = b;
for (i=0; i<n; i++) {
(*pb)++;
pb += 1024;
}
} while (loop_flag);

write(1,"\007",1);
if (!exit_flag)
kill(0,SIGSTOP);
exit(0);
}
-------------------------------------------------------------------------------
--- ps.c.ORIG Sat Jun 15 15:23:14 1996
+++ ps.c Sat Jun 15 15:50:05 1996
@@ -104,7 +104,7 @@
CL_sort = 1,
CL_forest,
CL_Sum,
- CL_pg_shift = 2; /* default: show k instead of pages */
+ CL_pg_shift = (PAGE_SHIFT-10); /* default: show k instead of pages */

/* Globals */

@@ -384,7 +384,7 @@
sprintf(wchanb, "%-9.9s", wchan(p->wchan));
sprintf(s, "%3x %5d %5d %5d %3d %2d %5d %5d %-10.10s %s %3s ",
p->flags, p->uid, p->pid, p->ppid, p->priority, p->nice,
- p->vsize >> 10, p->rss * 4, wchanb, status2(p), p->ttyc);
+ p->vsize >> 10, p->rss << (PAGE_SHIFT-10), wchanb, status2(p), p->ttyc);
}

void show_jobs(char *s, proc_t *p) {
@@ -410,10 +410,10 @@
(1000 * total_time) / (HZ * seconds) :
0;
if (pcpu > 999) pcpu = 999;
- pmem = p->rss * 1000 / (GL_main_mem >> 12);
+ pmem = p->rss * 1000 / (GL_main_mem >> PAGE_SHIFT);
sprintf(s, "%5d %2u.%u %2d.%d %5d %5d %2s %s%.6s ",
p->pid, pcpu / 10, pcpu % 10, pmem / 10, pmem % 10,
- p->vsize >> 10, p->rss << 2, p->ttyc, status2(p),
+ p->vsize >> 10, p->rss << (PAGE_SHIFT-10), p->ttyc, status2(p),
ctime(&start) + (GL_time_now - start > 3600*24 ? 4 : 10));
}

@@ -433,12 +433,12 @@
p->maj_flt + (CL_Sum ? p->cmaj_flt : 0),
(p->end_code - p->start_code) >> 10, /* XXX fixme! */
(p->vsize - p->end_code + p->start_code) >> 10, /* XXX */
- p->rss << 2);
+ p->rss << (PAGE_SHIFT-10));
if(p->rss_rlim == RLIM_INFINITY)
s += sprintf(s, " xx ");
else
s += sprintf(s, "%5d ", p->rss_rlim >> 10);
- pmem = p->rss * 1000 / (GL_main_mem >> 12);
+ pmem = p->rss * 1000 / (GL_main_mem >> PAGE_SHIFT);
sprintf(s, "%2d.%d ", pmem / 10, pmem % 10);
}

--- top.c.ORIG Sat Jun 15 17:07:50 1996
+++ top.c Sat Jun 15 15:41:47 1996
@@ -489,7 +490,7 @@
pmem = best->rss * 1000 / (main_mem >> 12);
printf("\n%5d %-8s %3d %3d %4d %4d %4d %s %2d.%d %2d.%d",
best->pid, best->user, best->priority, best->nice,
- best->vsize >> 10, best->rss * 4,
+ best->vsize >> 10, best->rss << (PAGE_SHIFT-10),
best->statm.share << 2, stat, pcpu / 10, pcpu % 10,
pmem / 10, pmem % 10);

-------------------------------------------------------------------------------

-- 
All SCSI disks will from now on                     ___       _____
be required to send an email notice                0--,|    /OOOOOOO\
24 hours prior to complete hardware failure!      <_/  /  /OOOOOOOOOOO\
                                                    \  \/OOOOOOOOOOOOOOO\
                                                      \ OOOOOOOOOOOOOOOOO|//
Harald Koenig,                                         \/\/\/\/\/\/\/\/\/
Inst.f.Theoret.Astrophysik                              //  /     \\  \
koenig@tat.physik.uni-tuebingen.de                     ^^^^^       ^^^^^