Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 27 Jan 1997 00:50:34 +1100
From:      Bruce Evans <bde@zeta.org.au>
To:        dg@root.com, swallace@ece.uci.edu
Cc:        current@FreeBSD.ORG
Subject:   Re: exec bug
Message-ID:  <199701261350.AAA31786@godzilla.zeta.org.au>

next in thread | raw e-mail | index | archive | help
>   The only solution I can think of at the moment to this problem would be to
>change the code to do a read of the file header into a malloced buffer. The
>overhead for this would be very (unacceptably) high, however.

Testing shows that the additional overhead would probably be small and
negative, since it is small and negative outside the kernel.  On a P133,
the enclosed program prints the following times for various access sizes:

	mmap	read	malloc+read
4:	39	22	125		(usec)
32:	40	22	125
1024:	44	34	135
4096:	60	72	160

I guess mmap is slower to start up because pagefaults have more overhead
than reads.

What is the library malloc()+free() doing to be 5 times slower than
read+lseek()?  The kernel malloc() is fast enough to use :-).  It takes
a couple of usec for small allocations.

The overheads when the header block isn't in memory are so much larger
that the reading method probably doesn't matter unless it is completely
unsuitable.  It's not clear whether read-ahead would be good or bad.

Bruce

---
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/time.h>

#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>

#define	NITER		1000
#define	PAGE_SIZE	4096

int main(int argc, char **argv)
{
	size_t access_size;
	char buf[PAGE_SIZE];
	int fd, i, j;
	char *malbuf;
	caddr_t p;
	struct timeval tv0, tv1;

	access_size = argc > 1 ? strtol(argv[1], NULL, 0) : 32;
	fd = open("/bin/cat", O_RDONLY);
	if (gettimeofday(&tv0, NULL) != 0)
		perror("gettimeofday 1");
	for (i = 0; i < NITER; ++i) {
		p = mmap((caddr_t)0, PAGE_SIZE, PROT_READ, 0, fd, (off_t)0);
		if (p == MAP_FAILED)
			perror("mmap");
		for (j = 0; j < access_size; j += sizeof(int))
			*(volatile int *)(p + j);
		if (munmap(p, PAGE_SIZE) != 0)
			perror("munmap");
	}
	if (gettimeofday(&tv1, NULL) != 0)
		perror("gettimeofday 2");
	printf("mmap time = %.0f usec\n",
	       (1e6 * (tv1.tv_sec - tv0.tv_sec) + (tv1.tv_usec - tv0.tv_usec))
	       / NITER);

	if (gettimeofday(&tv0, NULL) != 0)
		perror("gettimeofday 3");
	for (i = 0; i < NITER; ++i) {
		if (read(fd, buf, access_size) != access_size)
			perror("read");
		if (lseek(fd, (off_t)0, SEEK_SET) != 0)
			perror("lseek");
	}
	if (gettimeofday(&tv1, NULL) != 0)
		perror("gettimeofday 4");
	printf("read time = %.0f usec\n",
	       (1e6 * (tv1.tv_sec - tv0.tv_sec) + (tv1.tv_usec - tv0.tv_usec))
	       / NITER);

	if (gettimeofday(&tv0, NULL) != 0)
		perror("gettimeofday 5");
	for (i = 0; i < NITER; ++i) {
		/* malloc()/free() is much slower than read()! */
		malbuf = malloc(PAGE_SIZE);
		if (malbuf == NULL)
			perror("malloc");
		if (read(fd, malbuf, access_size) != access_size)
			perror("read");
		if (lseek(fd, (off_t)0, SEEK_SET) != 0)
			perror("lseek");
		free(malbuf);
	}
	if (gettimeofday(&tv1, NULL) != 0)
		perror("gettimeofday 6");
	printf("malloc+read time = %.0f usec\n",
	       (1e6 * (tv1.tv_sec - tv0.tv_sec) + (tv1.tv_usec - tv0.tv_usec))
	       / NITER);

	return 0;
}
---



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199701261350.AAA31786>