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