5 #include "perf_index.h"
7 #include <sys/socket.h>
10 #define CONTROL_PORT 17694
12 static const stress_test_t
*stress_tests
[] =
13 {&cpu_test
, &memory_test
, &syscall_test
, &fault_test
, &zfod_test
,
14 &file_local_create_test
, &file_local_write_test
, &file_local_read_test
,
15 &file_ram_create_test
, &file_ram_read_test
, &file_ram_write_test
, &iperf_test
,
19 static int num_threads
;
20 static long long all_len
;
22 static const char *control_host
= NULL
;
23 static const char **test_argv
;
25 struct in_addr control_host_addr
;
27 const char remote_str
[] = "remote";
28 const char ready_msg
[] = "Ready";
29 const char done_msg
[] = "Done";
31 static pthread_cond_t threads_running_cvar
;
32 static pthread_cond_t start_cvar
;
33 static int thread_count
;
34 static pthread_mutex_t count_lock
;
38 fprintf(stderr
, "usage: perf_index remote server\n"
40 "usage: pref_index type threads size [args]\n\n"
41 "where type is one of:\n");
42 for(i
=0; i
<sizeof(stress_tests
)/sizeof(stress_test_t
*); i
++) {
43 fprintf(stderr
, "%s ", stress_tests
[i
]->name
);
45 fprintf(stderr
, "\n");
49 static int validate_args(int argc
, const char **argv
) {
57 if(argc
==3 && strcmp(argv
[1], remote_str
) == 0)
65 for(i
=0; i
<sizeof(stress_tests
)/sizeof(stress_test_t
*); i
++) {
66 if(strcmp(argv
[1], stress_tests
[i
]->name
) == 0) {
76 if(stress_tests
[i
]->validate(argc
-4, argv
+4))
82 int host_to_addr(const char *hostname
, struct in_addr
*addr
) {
83 struct addrinfo
*info
;
85 if((err
= getaddrinfo(hostname
, NULL
, NULL
, &info
)) != 0) {
88 *addr
= ((struct sockaddr_in
*)info
->ai_addr
)->sin_addr
;
93 static void parse_args(int argc
, const char **argv
);
95 static void read_params_from_server(void) {
96 struct sockaddr_in addr
;
102 const char **newargv
= malloc(sizeof(char*) * 4);
103 assert(newargv
!= NULL
);
105 if(host_to_addr(control_host
, &control_host_addr
)<0) {
106 fprintf(stderr
, "Could not resolve: %s\n", control_host
);
110 control_sock
= socket(PF_INET
, SOCK_STREAM
, 0);
111 assert(control_sock
!= -1);
112 addr
.sin_family
= AF_INET
;
113 addr
.sin_port
= htons(CONTROL_PORT
);
114 addr
.sin_addr
= control_host_addr
;
115 bzero(addr
.sin_zero
, sizeof addr
.sin_zero
);
116 if(connect(control_sock
, (struct sockaddr
*)&addr
, sizeof(struct sockaddr
)) == -1) {
117 fprintf(stderr
, "Failed to connect to host: %s\n", control_host
);
121 while(offset
<sizeof(readbuff
)) {
122 recv_count
= recv(control_sock
, readbuff
+offset
, sizeof(readbuff
) - offset
, 0);
124 fprintf(stderr
, "Failed to receive parameters\n");
128 /* Guard against bad input */
129 readbuff
[sizeof(readbuff
)-1] = '\0';
130 newargv
[1] = strdup(readbuff
);
131 for(i
=offset
; i
<offset
+recv_count
; i
++) {
132 if(readbuff
[i
] == '\0') {
134 newargv
[zerocount
+1] = strdup(&readbuff
[i
+1]);
137 offset
+= recv_count
;
138 if(offset
>=2 && readbuff
[offset
-1] == '\0' && readbuff
[offset
-2] == '\0')
142 fprintf(stderr
, "Received invalid parameters");
146 parse_args(zerocount
+1, newargv
);
149 static void parse_args(int argc
, const char **argv
) {
150 test_type
= validate_args(argc
, argv
);
153 if(strcmp(argv
[1], remote_str
) == 0) {
154 control_host
= argv
[2];
155 read_params_from_server();
158 num_threads
= strtoimax(argv
[2], NULL
, 10);
159 all_len
= strtoll(argv
[3], NULL
, 10);
160 test_argc
= argc
- 4;
161 test_argv
= argv
+ 4;
165 static void *stress_loop(void *data
) {
166 int my_index
= (int)data
;
167 long long work_size
= all_len
/ num_threads
;
168 int work_remainder
= all_len
% num_threads
;
170 if(work_remainder
> my_index
) {
174 pthread_mutex_lock(&count_lock
);
176 if(thread_count
== num_threads
)
177 pthread_cond_signal(&threads_running_cvar
);
178 pthread_cond_wait(&start_cvar
, &count_lock
);
179 pthread_mutex_unlock(&count_lock
);
180 stress_tests
[test_type
]->stress(my_index
, num_threads
, work_size
, test_argc
, test_argv
);
184 void start_timer(struct timeval
*tp
) {
185 gettimeofday(tp
, NULL
);
188 void end_timer(struct timeval
*tp
) {
190 gettimeofday(&tend
, NULL
);
191 if(tend
.tv_usec
>= tp
->tv_usec
) {
192 tp
->tv_sec
= tend
.tv_sec
- tp
->tv_sec
;
193 tp
->tv_usec
= tend
.tv_usec
- tp
->tv_usec
;
196 tp
->tv_sec
= tend
.tv_sec
- tp
->tv_sec
- 1;
197 tp
->tv_usec
= tend
.tv_usec
- tp
->tv_usec
+ 1000000;
201 void print_timer(struct timeval
*tp
) {
202 printf("%ld.%06d", tp
->tv_sec
, tp
->tv_usec
);
205 void wait_start(void) {
207 if(control_host
!= NULL
) {
208 send(control_sock
, ready_msg
, strlen(ready_msg
), 0);
209 while(recv(control_sock
, readbuff
, sizeof(readbuff
), 0)>0);
214 send(control_sock
, done_msg
, strlen(done_msg
), 0);
217 int main(int argc
, const char **argv
) {
220 parse_args(argc
, argv
);
221 struct timeval timer
;
223 stress_tests
[test_type
]->init(num_threads
, all_len
, test_argc
, test_argv
);
224 pthread_cond_init(&threads_running_cvar
, NULL
);
225 pthread_cond_init(&start_cvar
, NULL
);
226 pthread_mutex_init(&count_lock
, NULL
);
229 threads
= (pthread_t
*)malloc(sizeof(pthread_t
)*num_threads
);
230 for(thread_index
= 0; thread_index
< num_threads
; thread_index
++) {
231 assert(pthread_create(&threads
[thread_index
], NULL
, stress_loop
, (void*)thread_index
) == 0);
234 pthread_mutex_lock(&count_lock
);
235 if(thread_count
!= num_threads
)
236 pthread_cond_wait(&threads_running_cvar
, &count_lock
);
237 pthread_mutex_unlock(&count_lock
);
242 pthread_cond_broadcast(&start_cvar
);
243 for(thread_index
= 0; thread_index
< num_threads
; thread_index
++) {
244 pthread_join(threads
[thread_index
], NULL
);
249 pthread_mutex_destroy(&count_lock
);
250 pthread_cond_destroy(&start_cvar
);
251 pthread_cond_destroy(&threads_running_cvar
);
253 stress_tests
[test_type
]->cleanup(num_threads
, all_len
);