ping_pong.c
1 |
/*
|
---|---|
2 |
this measures the ping-pong byte range lock latency. It is
|
3 |
especially useful on a cluster of nodes sharing a common lock
|
4 |
manager as it will give some indication of the lock managers
|
5 |
performance under stress
|
6 |
|
7 |
tridge@samba.org, February 2002
|
8 |
|
9 |
*/
|
10 |
|
11 |
#include <stdio.h> |
12 |
#include <stdlib.h> |
13 |
#include <sys/time.h> |
14 |
#include <time.h> |
15 |
#include <errno.h> |
16 |
#include <string.h> |
17 |
#include <unistd.h> |
18 |
#include <fcntl.h> |
19 |
#include <getopt.h> |
20 |
#include <sys/mman.h> |
21 |
|
22 |
static struct timeval tp1,tp2; |
23 |
|
24 |
static int do_reads, do_writes, use_mmap; |
25 |
|
26 |
static void start_timer() |
27 |
{ |
28 |
gettimeofday(&tp1,NULL);
|
29 |
} |
30 |
|
31 |
static double end_timer() |
32 |
{ |
33 |
gettimeofday(&tp2,NULL);
|
34 |
return (tp2.tv_sec + (tp2.tv_usec*1.0e-6)) - |
35 |
(tp1.tv_sec + (tp1.tv_usec*1.0e-6)); |
36 |
} |
37 |
|
38 |
/* lock a byte range in a open file */
|
39 |
static int lock_range(int fd, int offset, int len) |
40 |
{ |
41 |
struct flock lock;
|
42 |
|
43 |
lock.l_type = F_WRLCK; |
44 |
lock.l_whence = SEEK_SET; |
45 |
lock.l_start = offset; |
46 |
lock.l_len = len; |
47 |
lock.l_pid = 0;
|
48 |
|
49 |
return fcntl(fd,F_SETLKW,&lock);
|
50 |
} |
51 |
|
52 |
/* unlock a byte range in a open file */
|
53 |
static int unlock_range(int fd, int offset, int len) |
54 |
{ |
55 |
struct flock lock;
|
56 |
|
57 |
lock.l_type = F_UNLCK; |
58 |
lock.l_whence = SEEK_SET; |
59 |
lock.l_start = offset; |
60 |
lock.l_len = len; |
61 |
lock.l_pid = 0;
|
62 |
|
63 |
return fcntl(fd,F_SETLKW,&lock);
|
64 |
} |
65 |
|
66 |
/* run the ping pong test on fd */
|
67 |
static void ping_pong(int fd, int num_locks) |
68 |
{ |
69 |
unsigned count = 0; |
70 |
int i=0, loops=0; |
71 |
unsigned char *val; |
72 |
unsigned char incr=0, last_incr=0; |
73 |
unsigned char *p = NULL; |
74 |
|
75 |
ftruncate(fd, num_locks+1);
|
76 |
|
77 |
if (use_mmap) {
|
78 |
p = mmap(NULL, num_locks+1, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); |
79 |
} |
80 |
|
81 |
val = (unsigned char *)calloc(num_locks+1, sizeof(unsigned char)); |
82 |
|
83 |
start_timer(); |
84 |
|
85 |
lock_range(fd, 0, 1); |
86 |
i = 0;
|
87 |
|
88 |
while (1) { |
89 |
if (lock_range(fd, (i+1) % num_locks, 1) != 0) { |
90 |
printf("lock at %d failed! - %s\n",
|
91 |
(i+1) % num_locks, strerror(errno));
|
92 |
} |
93 |
if (do_reads) {
|
94 |
unsigned char c; |
95 |
if (use_mmap) {
|
96 |
c = p[i]; |
97 |
} else if (pread(fd, &c, 1, i) != 1) { |
98 |
printf("read failed at %d\n", i);
|
99 |
} |
100 |
incr = c - val[i]; |
101 |
val[i] = c; |
102 |
} |
103 |
if (do_writes) {
|
104 |
char c = val[i] + 1; |
105 |
if (use_mmap) {
|
106 |
p[i] = c; |
107 |
} else if (pwrite(fd, &c, 1, i) != 1) { |
108 |
printf("write failed at %d\n", i);
|
109 |
} |
110 |
} |
111 |
if (unlock_range(fd, i, 1) != 0) { |
112 |
printf("unlock at %d failed! - %s\n",
|
113 |
i, strerror(errno)); |
114 |
} |
115 |
i = (i+1) % num_locks;
|
116 |
count++; |
117 |
if (loops > num_locks && incr != last_incr) {
|
118 |
last_incr = incr; |
119 |
printf("data increment = %u\n", incr);
|
120 |
fflush(stdout); |
121 |
} |
122 |
if (end_timer() > 1.0) { |
123 |
printf("%8u locks/sec\r",
|
124 |
(unsigned)(2*count/end_timer())); |
125 |
fflush(stdout); |
126 |
start_timer(); |
127 |
count=0;
|
128 |
} |
129 |
loops++; |
130 |
} |
131 |
} |
132 |
|
133 |
int main(int argc, char *argv[]) |
134 |
{ |
135 |
char *fname;
|
136 |
int fd, num_locks;
|
137 |
int c;
|
138 |
|
139 |
while ((c = getopt(argc, argv, "rwm")) != -1) { |
140 |
switch (c){
|
141 |
case 'w': |
142 |
do_writes = 1;
|
143 |
break;
|
144 |
case 'r': |
145 |
do_reads = 1;
|
146 |
break;
|
147 |
case 'm': |
148 |
use_mmap = 1;
|
149 |
break;
|
150 |
default:
|
151 |
fprintf(stderr, "Unknown option '%c'\n", c);
|
152 |
exit(1);
|
153 |
} |
154 |
} |
155 |
|
156 |
argv += optind; |
157 |
argc -= optind; |
158 |
|
159 |
if (argc < 2) { |
160 |
printf("ping_pong [options] <file> <num_locks>\n");
|
161 |
printf(" -r do reads\n");
|
162 |
printf(" -w do writes\n");
|
163 |
printf(" -m use mmap\n");
|
164 |
exit(1);
|
165 |
} |
166 |
|
167 |
fname = argv[0];
|
168 |
num_locks = atoi(argv[1]);
|
169 |
|
170 |
fd = open(fname, O_CREAT|O_RDWR, 0600);
|
171 |
if (fd == -1) exit(1); |
172 |
|
173 |
ping_pong(fd, num_locks); |
174 |
|
175 |
return 0; |
176 |
} |