Project

General

Profile

ping_pong.c

Eric Eastman, 08/10/2015 03:39 AM

Download (3.34 KB)

 
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
}