Date: Mon, 12 Jul 1999 10:41:10 -0700 (PDT) From: Matthew Dillon <dillon@apollo.backplane.com> To: Matthew Dillon <dillon@apollo.backplane.com> Cc: Poul-Henning Kamp <phk@critter.freebsd.dk>, Luoqi Chen <luoqi@watermarkgroup.com>, dfr@nlsystems.com, jeremyp@gsmx07.alcatel.com.au, freebsd-current@FreeBSD.ORG, mike@ducky.net Subject: lock prefix overhead in SMP system - results Message-ID: <199907121741.KAA70496@apollo.backplane.com>
next in thread | raw e-mail | index | archive | help
Ok, here we are. The lock instruction overhead is significant relative
the execution time of the instruction, though on a 450 MHz P-III it is
still not a huge problem. Basically 12 vs 89 ns for the non competitive
case, and 26 vs 161 ns for the competitive case.
empty loop 9.33 ns/loop mode 0
1proc no locks 12.86 ns/loop mode 9
2proc no locks 26.16 ns/loop mode 10
1proc w/ locks 89.87 ns/loop mode 1
2proc w/ locks 161.09 ns/loop mode 2
If you modify the source code and add three nop() calls inside the loop
for case 9 and 1 (which also covers 10 and 2), which avoids some of the
synchronization overhead, you get numbers closer to what I expect in the
real world. ( recompile the code -DREAL_WORLD )
empty loop 9.33 ns/loop mode 0
1proc no locks 55.89 ns/loop
2proc no locks 129.96 ns/loop
1proc w/ locks 98.35 ns/loop
2proc w/ locks 160.96 ns/loop
/*
* Compile -O2
*/
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <stdarg.h>
#include <unistd.h>
#define LOOPS 10000000
#define ATOMIC_ASM(type,op) \
__asm __volatile ("lock; " op : "=m" (*(type *)p) : "ir" (v), "0" (*(type *)p))
#define ATOMIC_ASM_NOLOCK(type,op) \
__asm __volatile (op : "=m" (*(type *)p) : "ir" (v), "0" (*(type *)p))
static __inline void
atomic_add_int(void *p, u_int v)
{
ATOMIC_ASM(int, "addl %1,%0");
}
static __inline void
atomic_add_int_nolock(void *p, u_int v)
{
ATOMIC_ASM_NOLOCK(int, "addl %1,%0");
}
void
nop(void)
{
}
int
main(int ac, char **av)
{
int fd;
char *ptr;
char *wlocks;
int pgsize = getpagesize();
volatile int i;
int m;
int usec;
pid_t pid = -1;
struct timeval tv1;
struct timeval tv2;
if (ac == 1) {
printf("%s {0,1,2}\n", av[0]);
printf(" 0 - empty loop\n");
printf(" 1 - one process\n");
printf(" 2 - two processes\n");
printf(" 8 - empty loop - no lock\n");
printf(" 9 - one process - no lock\n");
printf(" 10- two processes - no lock\n");
exit(1);
}
m = strtol(av[1], NULL, 0);
fd = open("test.dat", O_RDWR|O_CREAT|O_TRUNC, 0666);
ftruncate(fd, pgsize);
ptr = mmap(NULL, pgsize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if (m & 8)
wlocks = "";
else
wlocks = " w/locks";
gettimeofday(&tv1, NULL);
switch(m) {
case 10:
pid = fork();
/* fall through */
case 9:
for (i = 0; i < LOOPS; ++i) {
atomic_add_int_nolock(ptr, 1);
#ifdef REAL_WORLD
nop();
nop();
nop();
#endif
}
break;
case 8:
for (i = 0; i < LOOPS; ++i) {
;
}
break;
case 2:
pid = fork();
/* fall through */
case 1:
for (i = 0; i < LOOPS; ++i) {
atomic_add_int(ptr, 1);
#ifdef REAL_WORLD
nop();
nop();
nop();
#endif
}
break;
case 0:
for (i = 0; i < LOOPS; ++i) {
;
}
break;
default:
printf("huh?\n");
exit(1);
}
if (pid == 0)
_exit(0);
while (wait(NULL) > 0)
;
gettimeofday(&tv2, NULL);
usec = tv2.tv_usec + 1000000 - tv1.tv_usec + (tv2.tv_sec - tv1.tv_sec - 1) * 1000000;
switch(m) {
case 0:
case 8:
printf("empty%s %4.2f ns/loop\n", wlocks, (double)usec * 1000.0 / (double)LOOPS);
break;
case 1:
case 9:
printf("1proc%s %4.2f ns/loop\n", wlocks, (double)usec * 1000.0 / (double)LOOPS);
break;
case 2:
case 10:
printf("2proc%s %4.2f ns/loop\n", wlocks, (double)usec * 1000.0 / (double)LOOPS / 2.0);
break;
}
return(0);
}
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199907121741.KAA70496>
