205 lines
3.5 KiB
C
205 lines
3.5 KiB
C
/*
|
|
* bloat - waste memory.
|
|
*
|
|
* This test allocates memory a page at a time and keeps going until
|
|
* it runs out. It gets the memory directly with sbrk to avoid malloc-
|
|
* related overheads, which as long as OS/161 has a dumb userlevel
|
|
* malloc is important for performance.
|
|
*/
|
|
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <assert.h>
|
|
#include <err.h>
|
|
|
|
/* OS/161 doesn't currently have a way to get this from the kernel. */
|
|
#define PAGE_SIZE 4096
|
|
|
|
/* the memory we've gotten */
|
|
static void *firstpage;
|
|
static void *lastpage;
|
|
|
|
/* number of page allocations per cycle */
|
|
static unsigned allocs;
|
|
|
|
/* number of pages to touch every cycle */
|
|
static unsigned touchpages;
|
|
|
|
/* when touching pages, the extent to which we favor the middle of the range */
|
|
static unsigned bias;
|
|
|
|
|
|
static
|
|
void
|
|
moremem(void)
|
|
{
|
|
static unsigned totalpages;
|
|
|
|
void *ptr;
|
|
unsigned i;
|
|
|
|
for (i=0; i<allocs; i++) {
|
|
ptr = sbrk(PAGE_SIZE);
|
|
if (ptr == (void *)-1) {
|
|
err(1, "After %u pages: sbrk", totalpages);
|
|
}
|
|
totalpages++;
|
|
lastpage = ptr;
|
|
if (firstpage == NULL) {
|
|
firstpage = ptr;
|
|
}
|
|
}
|
|
}
|
|
|
|
static
|
|
void
|
|
touchpage(unsigned pagenum)
|
|
{
|
|
int *ptr;
|
|
|
|
ptr = (void *)((uintptr_t)firstpage + PAGE_SIZE * pagenum);
|
|
*ptr = pagenum;
|
|
}
|
|
|
|
static
|
|
unsigned
|
|
pickpage(unsigned numpages)
|
|
{
|
|
unsigned mnum, moffset;
|
|
unsigned span, val, i;
|
|
|
|
/* take 1 in 1000 pages uniformly from the entire space */
|
|
if (random() % 1000 == 0) {
|
|
return random() % numpages;
|
|
}
|
|
|
|
/* the rest is taken from the middle 1% */
|
|
|
|
mnum = numpages / 100;
|
|
if (mnum < touchpages * 2) {
|
|
mnum = touchpages * 2;
|
|
}
|
|
if (mnum >= numpages) {
|
|
mnum = numpages;
|
|
}
|
|
moffset = numpages / 2 - mnum / 2;
|
|
|
|
assert(bias >= 1);
|
|
span = (mnum + bias - 1) / bias;
|
|
|
|
do {
|
|
val = 0;
|
|
for (i=0; i<bias; i++) {
|
|
val += random() % span;
|
|
}
|
|
} while (val >= mnum);
|
|
return moffset + val;
|
|
}
|
|
|
|
static
|
|
void
|
|
touchmem(void)
|
|
{
|
|
unsigned i, num;
|
|
|
|
num = (((uintptr_t)lastpage - (uintptr_t)firstpage) / PAGE_SIZE) + 1;
|
|
|
|
if (num % 256 == 0) {
|
|
warnx("%u pages", num);
|
|
}
|
|
|
|
for (i=0; i<touchpages; i++) {
|
|
touchpage(pickpage(num));
|
|
}
|
|
}
|
|
|
|
static
|
|
void
|
|
run(void)
|
|
{
|
|
while (1) {
|
|
moremem();
|
|
touchmem();
|
|
}
|
|
}
|
|
|
|
static
|
|
void
|
|
printsettings(void)
|
|
{
|
|
tprintf("Page size: %u\n", PAGE_SIZE);
|
|
tprintf("Allocating %u pages and touching %u pages on each cycle.\n",
|
|
allocs, touchpages);
|
|
tprintf("Page selection bias: %u\n", bias);
|
|
tprintf("\n");
|
|
}
|
|
|
|
static
|
|
void
|
|
usage(void)
|
|
{
|
|
warnx("bloat [-a allocs] [-b bias] [-p pages]");
|
|
warnx(" allocs: number of pages allocated per cycle (default 4)");
|
|
warnx(" bias: number of dice rolled to touch pages (default 8)");
|
|
warnx(" pages: pages touched per cycle (default 8)");
|
|
exit(1);
|
|
}
|
|
|
|
int
|
|
main(int argc, char *argv[])
|
|
{
|
|
int i;
|
|
|
|
/* default mode */
|
|
allocs = 4;
|
|
touchpages = 8;
|
|
bias = 8;
|
|
|
|
srandom(1234);
|
|
|
|
for (i=1; i<argc; i++) {
|
|
if (!strcmp(argv[i], "-a")) {
|
|
i++;
|
|
if (i == argc) {
|
|
errx(1, "-a: option requires argument");
|
|
}
|
|
allocs = atoi(argv[i]);
|
|
if (allocs == 0) {
|
|
errx(1, "-a: must not be zero");
|
|
}
|
|
}
|
|
else if (!strcmp(argv[i], "-b")) {
|
|
i++;
|
|
if (i == argc) {
|
|
errx(1, "-b: option requires argument");
|
|
}
|
|
bias = atoi(argv[i]);
|
|
if (bias == 0) {
|
|
errx(1, "-b: must not be zero");
|
|
}
|
|
}
|
|
else if (!strcmp(argv[i], "-h")) {
|
|
usage();
|
|
}
|
|
else if (!strcmp(argv[i], "-p")) {
|
|
i++;
|
|
if (i == argc) {
|
|
errx(1, "-p: option requires argument");
|
|
}
|
|
touchpages = atoi(argv[i]);
|
|
}
|
|
else {
|
|
errx(1, "Argument %s not recognized", argv[i]);
|
|
usage();
|
|
}
|
|
}
|
|
|
|
printsettings();
|
|
run();
|
|
return 0;
|
|
}
|