Subject: memory tester shows up swap/page tuning bug
To: None <Havard.Eidnes@runit.sintef.no>
From: Jonathan Stone <jonathan@DSG.Stanford.EDU>
List: current-users
Date: 09/14/1996 15:47:56
Hvard Eidnes writes:
>> > The reason I'm curious is that we are once again having
>> > problems with occasional 15-20 second "lockups" of the
>> > machines when they start swapping. [...]
>>
>> Me too.  The same happens on i386 and Sparc.  Pretty annoying. :-(

>You guys may want to go back and read Sean Doran's message sent
>to port-sparc on August 10 under the subject "System slowdown
>during paging", where he suggests tweaking the MAXSLP define in
>/sys/arch/xxx/include/vmparam.h.

I've read Sean's message. It looks like it will only postpone the
the problem, and only  for some memory-usage patterns.

The following shar'ed program allocates and touches large amounts of
physical memory.  (I wrote it to check for a bad SIMM).  Run it with
the size, in megabytes, of physical memory on the machine. Do this
where you can hear swapping activity to the disk. During the
``interesting'' behaviour regime, normal tools don't seem able to run,
at least not for me.

IMNSO, a VM system should keep a pool of free pageframes at all times,
to satisfy pagefaults without having to first page something else out.

It *may* (emphasis on the "may") be that NetBSD is failing to do this
in some circumstances.  I don't really know how to diagnose this,
when the user-level tools I'd normally use are also getting stomped.



# This is a shell archive.  Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file".  Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
#	memtest.c
#
echo x - memtest.c
sed 's/^X//' >memtest.c << 'END-of-memtest.c'
X/*
X * Write test pattern into N megabytes of virtual memory.
X * May also induce thrashing or demonstrate VM performance problems
X * when the size tested is at or near physical memory size.
X */
X
X
X#include <stdio.h>
X#include <stdlib.h>
X#include <unistd.h>
X
X#define ONE_MBYTE (1024* 1024)
X
X/*
X *  Flags
X */
Xint verboseflag = 0;
Xint foreverflag = 0;
X
X
X/*
X * Fill a hunk of memory with a test pattern, then do a read-after-write
X * comparison.
X */
Xint
Xmemtest (int *mem, int size, int pattern)
X{
X	register int i;
X	
X	for (i = 0; i < size; i++) {
X		mem[i] = pattern ;
X	}
X
X	for (i = 0; i < size; i++) {
X		if (mem[i] != pattern) {
X			printf("failed at %p, should be 0x%x, is 0x%x\n",
X			       mem+i, pattern, mem[i]);
X			((volatile int*)mem)[i] = pattern ;
X			if (mem[i] != pattern) 
X			printf("failed again at %p, should be 0x%x, is 0x%x\n",
X			       mem+i, pattern, mem[i]);
X		}
X	}
X}
X
Xvoid
Xusage()
X{
X	extern char *__progname;
X	printf("usage: %s [-v] [-f] <megabytes>\n", __progname);
X	exit(2);
X}
X
X
Xint
Xparseopts(int argc, char *argv[])
X{
X	extern int optind;
X	int ch;
X
X	while ((ch = getopt(argc, argv, "vf")) != -1) {
X		switch (ch) {
X		case 'v':
X			verboseflag = 1;
X			break;
X		case 'f':
X			foreverflag = 1;
X			break;
X		default:
X			usage();
X		}
X	}
X	
X	argc -= optind;
X	argv += optind;
X
X	if (argc != 1) usage();
X
X	return (atoi (argv[0]));
X}
X
X
X
Xint
Xmain(int argc, char *argv[])
X{
X	void  *p;
X	int i, megs;
X
X	megs = parseopts(argc, argv);
X	p = (void*)malloc(ONE_MBYTE * megs);
X
Xtest:
X	for (i = 0; i < megs; i++) {
X		int *thishunk = p+(ONE_MBYTE*i);
X		if (verboseflag)
X			printf("testing: %d Mbytes\n", i);
X		memtest(thishunk, (ONE_MBYTE / sizeof(int)), 0);
X		memtest(thishunk, (ONE_MBYTE / sizeof(int)), 0xffffffff);
X		memtest(thishunk, (ONE_MBYTE / sizeof(int)), 0xa5a5a5a5);
X		memtest(thishunk, (ONE_MBYTE / sizeof(int)), 0x5a5a5a5a);
X		memtest(thishunk, (ONE_MBYTE / sizeof(int)), 0);
X	}
X	if (foreverflag) goto test;
X}
END-of-memtest.c
exit