bin/memaslap: fix build
[m6w6/libmemcached] / src / bin / memaslap.c
1 /*
2 * memslap
3 *
4 * (c) Copyright 2009, Schooner Information Technology, Inc.
5 * All rights reserved.
6 * http://www.schoonerinfotech.com/
7 *
8 * Use and distribution licensed under the BSD license. See
9 * the COPYING file for full text.
10 *
11 * Authors:
12 * Brian Aker
13 * Mingqiang Zhuang <mingqiangzhuang@hengtiansoft.com>
14 *
15 */
16 #include "mem_config.h"
17
18 #include <stdlib.h>
19 #include <getopt.h>
20 #include <limits.h>
21
22 #if defined(HAVE_SYS_TIME_H)
23 # include <sys/time.h>
24 #endif
25
26 #if defined(HAVE_TIME_H)
27 # include <time.h>
28 #endif
29
30
31 #include "ms_sigsegv.h"
32 #include "ms_setting.h"
33 #include "ms_thread.h"
34
35 /* global structure */
36 ms_global_t ms_global;
37
38 /* global stats information structure */
39 ms_stats_t ms_stats;
40
41 /* global statistic structure */
42 ms_statistic_t ms_statistic;
43
44 #define PROGRAM_NAME "memslap"
45 #define PROGRAM_DESCRIPTION \
46 "Generates workload against memcached servers."
47
48 #ifdef __sun
49 /* For some odd reason the option struct on solaris defines the argument
50 * as char* and not const char*
51 */
52 #define OPTIONSTRING char*
53 #else
54 #define OPTIONSTRING const char*
55 #endif
56
57 /* options */
58 static struct option long_options[]=
59 {
60 { (OPTIONSTRING)"servers", required_argument, NULL,
61 OPT_SERVERS },
62 { (OPTIONSTRING)"threads", required_argument, NULL,
63 OPT_THREAD_NUMBER },
64 { (OPTIONSTRING)"concurrency", required_argument, NULL,
65 OPT_CONCURRENCY },
66 { (OPTIONSTRING)"conn_sock", required_argument, NULL,
67 OPT_SOCK_PER_CONN },
68 { (OPTIONSTRING)"execute_number", required_argument, NULL,
69 OPT_EXECUTE_NUMBER },
70 { (OPTIONSTRING)"time", required_argument, NULL,
71 OPT_TIME },
72 { (OPTIONSTRING)"cfg_cmd", required_argument, NULL,
73 OPT_CONFIG_CMD },
74 { (OPTIONSTRING)"win_size", required_argument, NULL,
75 OPT_WINDOW_SIZE },
76 { (OPTIONSTRING)"fixed_size", required_argument, NULL,
77 OPT_FIXED_LTH },
78 { (OPTIONSTRING)"verify", required_argument, NULL,
79 OPT_VERIFY },
80 { (OPTIONSTRING)"division", required_argument, NULL,
81 OPT_GETS_DIVISION },
82 { (OPTIONSTRING)"stat_freq", required_argument, NULL,
83 OPT_STAT_FREQ },
84 { (OPTIONSTRING)"exp_verify", required_argument, NULL,
85 OPT_EXPIRE },
86 { (OPTIONSTRING)"overwrite", required_argument, NULL,
87 OPT_OVERWRITE },
88 { (OPTIONSTRING)"reconnect", no_argument, NULL,
89 OPT_RECONNECT },
90 { (OPTIONSTRING)"udp", no_argument, NULL,
91 OPT_UDP },
92 { (OPTIONSTRING)"facebook", no_argument, NULL,
93 OPT_FACEBOOK_TEST },
94 { (OPTIONSTRING)"binary", no_argument, NULL,
95 OPT_BINARY_PROTOCOL },
96 { (OPTIONSTRING)"tps", required_argument, NULL,
97 OPT_TPS },
98 { (OPTIONSTRING)"rep_write", required_argument, NULL,
99 OPT_REP_WRITE_SRV },
100 { (OPTIONSTRING)"verbose", no_argument, NULL,
101 OPT_VERBOSE },
102 { (OPTIONSTRING)"help", no_argument, NULL,
103 OPT_HELP },
104 { (OPTIONSTRING)"version", no_argument, NULL,
105 OPT_VERSION },
106 { 0, 0, 0, 0 },
107 };
108
109 /* Prototypes */
110 static void ms_sync_lock_init(void);
111 static void ms_sync_lock_destroy(void);
112 static void ms_global_struct_init(void);
113 static void ms_global_struct_destroy(void);
114 static void ms_version_command(const char *command_name);
115 static const char *ms_lookup_help(ms_options_t option);
116 static int64_t ms_parse_time(void);
117 static int64_t ms_parse_size(void);
118 static void ms_options_parse(int argc, char *argv[]);
119 static int ms_check_para(void);
120 static void ms_statistic_init(void);
121 static void ms_stats_init(void);
122 static void ms_print_statistics(int in_time);
123 static void ms_print_memslap_stats(struct timeval *start_time,
124 struct timeval *end_time);
125 static void ms_monitor_slap_mode(void);
126
127 /**
128 * output the help information
129 *
130 * @param command_name, the string of this process
131 * @param description, description of this process
132 * @param long_options, global options array
133 */
134 static __attribute__((noreturn)) void ms_help_command(const char *command_name, const char *description)
135 {
136 char *help_message= NULL;
137
138 printf("%s v%u.%u\n", command_name, 1U, 0U);
139 printf(" %s\n\n", description);
140 printf(
141 "Usage:\n"
142 " memslap -hV | -s servers [-F config_file] [-t time | -x exe_num] [...]\n\n"
143 "Options:\n");
144
145 for (int x= 0; long_options[x].name; x++)
146 {
147 printf(" -%c, --%s%c\n", long_options[x].val, long_options[x].name,
148 long_options[x].has_arg ? '=' : ' ');
149
150 if ((help_message= (char *)ms_lookup_help(long_options[x].val)) != NULL)
151 {
152 printf(" %s\n", help_message);
153 }
154 }
155
156 printf(
157 "\nExamples:\n"
158 " memslap -s 127.0.0.1:11211 -S 5s\n"
159 " memslap -s 127.0.0.1:11211 -t 2m -v 0.2 -e 0.05 -b\n"
160 " memslap -s 127.0.0.1:11211 -F config -t 2m -w 40k -S 20s -o 0.2\n"
161 " memslap -s 127.0.0.1:11211 -F config -t 2m -T 4 -c 128 -d 20 -P 40k\n"
162 " memslap -s 127.0.0.1:11211 -F config -t 2m -d 50 -a -n 40\n"
163 " memslap -s 127.0.0.1:11211,127.0.0.1:11212 -F config -t 2m\n"
164 " memslap -s 127.0.0.1:11211,127.0.0.1:11212 -F config -t 2m -p 2\n\n");
165
166 exit(0);
167 } /* ms_help_command */
168
169
170 /* initialize the global locks */
171 static void ms_sync_lock_init()
172 {
173 ms_global.init_lock.count= 0;
174 pthread_mutex_init(&ms_global.init_lock.lock, NULL);
175 pthread_cond_init(&ms_global.init_lock.cond, NULL);
176
177 ms_global.warmup_lock.count = 0;
178 pthread_mutex_init(&ms_global.warmup_lock.lock, NULL);
179 pthread_cond_init(&ms_global.warmup_lock.cond, NULL);
180
181 ms_global.run_lock.count= 0;
182 pthread_mutex_init(&ms_global.run_lock.lock, NULL);
183 pthread_cond_init(&ms_global.run_lock.cond, NULL);
184
185 pthread_mutex_init(&ms_global.quit_mutex, NULL);
186 pthread_mutex_init(&ms_global.seq_mutex, NULL);
187 } /* ms_sync_lock_init */
188
189
190 /* destroy the global locks */
191 static void ms_sync_lock_destroy()
192 {
193 pthread_mutex_destroy(&ms_global.init_lock.lock);
194 pthread_cond_destroy(&ms_global.init_lock.cond);
195
196 pthread_mutex_destroy(&ms_global.warmup_lock.lock);
197 pthread_cond_destroy(&ms_global.warmup_lock.cond);
198
199 pthread_mutex_destroy(&ms_global.run_lock.lock);
200 pthread_cond_destroy(&ms_global.run_lock.cond);
201
202 pthread_mutex_destroy(&ms_global.quit_mutex);
203 pthread_mutex_destroy(&ms_global.seq_mutex);
204
205 if (ms_setting.stat_freq > 0)
206 {
207 pthread_mutex_destroy(&ms_statistic.stat_mutex);
208 }
209 } /* ms_sync_lock_destroy */
210
211
212 /* initialize the global structure */
213 static void ms_global_struct_init()
214 {
215 ms_sync_lock_init();
216 ms_global.finish_warmup= false;
217 ms_global.time_out= false;
218 }
219
220
221 /* destroy the global structure */
222 static void ms_global_struct_destroy()
223 {
224 ms_sync_lock_destroy();
225 }
226
227
228 /**
229 * output the version information
230 *
231 * @param command_name, the string of this process
232 */
233 static void ms_version_command(const char *command_name)
234 {
235 printf("%s v%u.%u\n", command_name, 1U, 0U);
236 exit(0);
237 }
238
239
240 /**
241 * get the description of the option
242 *
243 * @param option, option of command line
244 *
245 * @return char*, description of the command option
246 */
247 static const char *ms_lookup_help(ms_options_t option)
248 {
249 switch (option)
250 {
251 case OPT_SERVERS:
252 return
253 "List one or more servers to connect. Servers count must be less than\n"
254 " threads count. e.g.: --servers=localhost:1234,localhost:11211";
255
256 case OPT_VERSION:
257 return "Display the version of the application and then exit.";
258
259 case OPT_HELP:
260 return "Display this message and then exit.";
261
262 case OPT_EXECUTE_NUMBER:
263 return "Number of operations(get and set) to execute for the\n"
264 " given test. Default 1000000.";
265
266 case OPT_THREAD_NUMBER:
267 return
268 "Number of threads to startup, better equal to CPU numbers. Default 8.";
269
270 case OPT_CONCURRENCY:
271 return "Number of concurrency to simulate with load. Default 128.";
272
273 case OPT_FIXED_LTH:
274 return "Fixed length of value.";
275
276 case OPT_VERIFY:
277 return "The proportion of date verification, e.g.: --verify=0.01";
278
279 case OPT_GETS_DIVISION:
280 return "Number of keys to multi-get once. Default 1, means single get.";
281
282 case OPT_TIME:
283 return
284 "How long the test to run, suffix: s-seconds, m-minutes, h-hours,\n"
285 " d-days e.g.: --time=2h.";
286
287 case OPT_CONFIG_CMD:
288 return
289 "Load the configure file to get command,key and value distribution list.";
290
291 case OPT_WINDOW_SIZE:
292 return
293 "Task window size of each concurrency, suffix: K, M e.g.: --win_size=10k.\n"
294 " Default 10k.";
295
296 case OPT_UDP:
297 return
298 "UDP support, default memslap uses TCP, TCP port and UDP port of\n"
299 " server must be same.";
300
301 case OPT_EXPIRE:
302 return
303 "The proportion of objects with expire time, e.g.: --exp_verify=0.01.\n"
304 " Default no object with expire time";
305
306 case OPT_OVERWRITE:
307 return
308 "The proportion of objects need overwrite, e.g.: --overwrite=0.01.\n"
309 " Default never overwrite object.";
310
311 case OPT_STAT_FREQ:
312 return
313 "Frequency of dumping statistic information. suffix: s-seconds,\n"
314 " m-minutes, e.g.: --resp_freq=10s.";
315
316 case OPT_SOCK_PER_CONN:
317 return "Number of TCP socks per concurrency. Default 1.";
318
319 case OPT_RECONNECT:
320 return
321 "Reconnect support, when connection is closed it will be reconnected.";
322
323 case OPT_VERBOSE:
324 return
325 "Whether it outputs detailed information when verification fails.";
326
327 case OPT_FACEBOOK_TEST:
328 return
329 "Whether it enables facebook test feature, set with TCP and multi-get with UDP.";
330
331 case OPT_BINARY_PROTOCOL:
332 return
333 "Whether it enables binary protocol. Default with ASCII protocol.";
334
335 case OPT_TPS:
336 return "Expected throughput, suffix: K, e.g.: --tps=10k.";
337
338 case OPT_REP_WRITE_SRV:
339 return "The first nth servers can write data, e.g.: --rep_write=2.";
340
341 default:
342 return "Forgot to document this option :)";
343 } /* switch */
344 } /* ms_lookup_help */
345
346
347 /* used to parse the time string */
348 static int64_t ms_parse_time()
349 {
350 int64_t ret= 0;
351 char unit= optarg[strlen(optarg) - 1];
352
353 optarg[strlen(optarg) - 1]= '\0';
354 ret= atoi(optarg);
355
356 switch (unit)
357 {
358 case 'd':
359 case 'D':
360 ret*= 24;
361 /* fall through */
362 case 'h':
363 case 'H':
364 ret*= 60;
365 /* fall through */
366 case 'm':
367 case 'M':
368 ret*= 60;
369 /* fall through */
370 case 's':
371 case 'S':
372 break;
373
374 default:
375 ret= -1;
376 break;
377 } /* switch */
378
379 return ret;
380 } /* ms_parse_time */
381
382
383 /* used to parse the size string */
384 static int64_t ms_parse_size()
385 {
386 int64_t ret= -1;
387 char unit= optarg[strlen(optarg) - 1];
388
389 optarg[strlen(optarg) - 1]= '\0';
390 errno= 0;
391 ret= strtoll(optarg, (char **)NULL, 10);
392 if (errno != 0)
393 {
394 fprintf(stderr, "strtoll(optarg,..): %s\n", strerror(errno));
395 exit(1);
396 }
397
398 switch (unit)
399 {
400 case 'k':
401 case 'K':
402 ret*= 1024;
403 break;
404
405 case 'm':
406 case 'M':
407 ret*= 1024 * 1024;
408 break;
409
410 case 'g':
411 case 'G':
412 ret*= 1024 * 1024 * 1024;
413 break;
414
415 default:
416 ret= -1;
417 break;
418 } /* switch */
419
420 return ret;
421 } /* ms_parse_size */
422
423
424 /* used to parse the options of command line */
425 static void ms_options_parse(int argc, char *argv[])
426 {
427 int option_index= 0;
428 int option_rv;
429
430 while ((option_rv= getopt_long(argc, argv, "VhURbaBs:x:T:c:X:v:d:"
431 "t:S:F:w:e:o:n:P:p:",
432 long_options, &option_index)) != -1)
433 {
434 switch (option_rv)
435 {
436 case 0:
437 break;
438
439 case OPT_VERSION: /* --version or -V */
440 ms_version_command(PROGRAM_NAME);
441 break;
442
443 case OPT_HELP: /* --help or -h */
444 ms_help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION);
445 break;
446
447 case OPT_SERVERS: /* --servers or -s */
448 ms_setting.srv_str= strdup(optarg);
449 break;
450
451 case OPT_CONCURRENCY: /* --concurrency or -c */
452 errno= 0;
453 ms_setting.nconns= (uint32_t)strtoul(optarg, (char **) NULL, 10);
454 if (ms_setting.nconns <= 0 || errno != 0)
455 {
456 fprintf(stderr, "Concurrency must be greater than 0.:-)\n");
457 exit(1);
458 }
459 break;
460
461 case OPT_EXECUTE_NUMBER: /* --execute_number or -x */
462 errno= 0;
463 ms_setting.exec_num= (int)strtol(optarg, (char **) NULL, 10);
464 if (ms_setting.exec_num <= 0 || errno != 0)
465 {
466 fprintf(stderr, "Execute number must be greater than 0.:-)\n");
467 exit(1);
468 }
469 break;
470
471 case OPT_THREAD_NUMBER: /* --threads or -T */
472 errno= 0;
473 ms_setting.nthreads= (uint32_t)strtoul(optarg, (char **) NULL, 10);
474 if (ms_setting.nthreads <= 0 || errno != 0)
475 {
476 fprintf(stderr, "Threads number must be greater than 0.:-)\n");
477 exit(1);
478 }
479 break;
480
481 case OPT_FIXED_LTH: /* --fixed_size or -X */
482 errno= 0;
483 ms_setting.fixed_value_size= (size_t)strtoull(optarg, (char **) NULL, 10);
484 if ((ms_setting.fixed_value_size <= 0 || errno != 0)
485 || (ms_setting.fixed_value_size > MAX_VALUE_SIZE))
486 {
487 fprintf(stderr, "Value size must be between 0 and 1M.:-)\n");
488 exit(1);
489 }
490 break;
491
492 case OPT_VERIFY: /* --verify or -v */
493 ms_setting.verify_percent= atof(optarg);
494 if ((ms_setting.verify_percent <= 0)
495 || (ms_setting.verify_percent > 1.0))
496 {
497 fprintf(stderr, "Data verification rate must be "
498 "greater than 0 and less than 1.0. :-)\n");
499 exit(1);
500 }
501 break;
502
503 case OPT_GETS_DIVISION: /* --division or -d */
504 errno= 0;
505 ms_setting.mult_key_num= (int)strtol(optarg, (char **) NULL, 10);
506 if (ms_setting.mult_key_num <= 0 || errno != 0)
507 {
508 fprintf(stderr, "Multi-get key number must be greater than 0.:-)\n");
509 exit(1);
510 }
511 break;
512
513 case OPT_TIME: /* --time or -t */
514 ms_setting.run_time= (int)ms_parse_time();
515 if (ms_setting.run_time == -1)
516 {
517 fprintf(stderr, "Please specify the run time. :-)\n"
518 "'s' for second, 'm' for minute, 'h' for hour, "
519 "'d' for day. e.g.: --time=24h (means 24 hours).\n");
520 exit(1);
521 }
522
523 if (ms_setting.run_time == 0)
524 {
525 fprintf(stderr, "Running time can not be 0. :-)\n");
526 exit(1);
527 }
528 break;
529
530 case OPT_CONFIG_CMD: /* --cfg_cmd or -F */
531 ms_setting.cfg_file= strdup(optarg);
532 break;
533
534 case OPT_WINDOW_SIZE: /* --win_size or -w */
535 ms_setting.win_size= (size_t)ms_parse_size();
536 if (ms_setting.win_size == (size_t)-1)
537 {
538 fprintf(
539 stderr,
540 "Please specify the item window size. :-)\n"
541 "e.g.: --win_size=10k (means 10k task window size).\n");
542 exit(1);
543 }
544 break;
545
546 case OPT_UDP: /* --udp or -U*/
547 ms_setting.udp= true;
548 break;
549
550 case OPT_EXPIRE: /* --exp_verify or -e */
551 ms_setting.exp_ver_per= atof(optarg);
552 if ((ms_setting.exp_ver_per <= 0) || (ms_setting.exp_ver_per > 1.0))
553 {
554 fprintf(stderr, "Expire time verification rate must be "
555 "greater than 0 and less than 1.0. :-)\n");
556 exit(1);
557 }
558 break;
559
560 case OPT_OVERWRITE: /* --overwrite or -o */
561 ms_setting.overwrite_percent= atof(optarg);
562 if ((ms_setting.overwrite_percent <= 0)
563 || (ms_setting.overwrite_percent > 1.0))
564 {
565 fprintf(stderr, "Objects overwrite rate must be "
566 "greater than 0 and less than 1.0. :-)\n");
567 exit(1);
568 }
569 break;
570
571 case OPT_STAT_FREQ: /* --stat_freq or -S */
572 ms_setting.stat_freq= (int)ms_parse_time();
573 if (ms_setting.stat_freq == -1)
574 {
575 fprintf(stderr, "Please specify the frequency of dumping "
576 "statistic information. :-)\n"
577 "'s' for second, 'm' for minute, 'h' for hour, "
578 "'d' for day. e.g.: --time=24h (means 24 hours).\n");
579 exit(1);
580 }
581
582 if (ms_setting.stat_freq == 0)
583 {
584 fprintf(stderr, "The frequency of dumping statistic information "
585 "can not be 0. :-)\n");
586 exit(1);
587 }
588 break;
589
590 case OPT_SOCK_PER_CONN: /* --conn_sock or -n */
591 errno= 0;
592 ms_setting.sock_per_conn= (uint32_t)strtoul(optarg, (char **) NULL, 10);
593 if (ms_setting.sock_per_conn <= 0 || errno != 0)
594 {
595 fprintf(stderr, "Number of socks of each concurrency "
596 "must be greater than 0.:-)\n");
597 exit(1);
598 }
599 break;
600
601 case OPT_RECONNECT: /* --reconnect or -R */
602 ms_setting.reconnect= true;
603 break;
604
605 case OPT_VERBOSE: /* --verbose or -b */
606 ms_setting.verbose= true;
607 break;
608
609 case OPT_FACEBOOK_TEST: /* --facebook or -a */
610 ms_setting.facebook_test= true;
611 break;
612
613 case OPT_BINARY_PROTOCOL: /* --binary or -B */
614 ms_setting.binary_prot_= true;
615 break;
616
617 case OPT_TPS: /* --tps or -P */
618 ms_setting.expected_tps= (int)ms_parse_size();
619 if (ms_setting.expected_tps == -1)
620 {
621 fprintf(stderr,
622 "Please specify the item expected throughput. :-)\n"
623 "e.g.: --tps=10k (means 10k throughput).\n");
624 exit(1);
625 }
626 break;
627
628 case OPT_REP_WRITE_SRV: /* --rep_write or -p */
629 errno= 0;
630 ms_setting.rep_write_srv= (uint32_t)strtoul(optarg, (char **) NULL, 10);
631 if (ms_setting.rep_write_srv <= 0 || errno != 0)
632 {
633 fprintf(stderr,
634 "Number of replication writing server must be greater "
635 "than 0.:-)\n");
636 exit(1);
637 }
638 break;
639
640 case '?':
641 /* getopt_long already printed an error message. */
642 exit(1);
643
644 default:
645 abort();
646 } /* switch */
647 }
648 } /* ms_options_parse */
649
650
651 static int ms_check_para()
652 {
653 if (ms_setting.srv_str == NULL)
654 {
655 char *temp;
656
657 if ((temp= getenv("MEMCACHED_SERVERS")))
658 {
659 ms_setting.srv_str= strdup(temp);
660 }
661 else
662 {
663 fprintf(stderr, "No Servers provided\n\n");
664 return -1;
665 }
666 }
667
668 if (ms_setting.nconns % (uint32_t)ms_setting.nthreads != 0)
669 {
670 fprintf(stderr, "Concurrency must be the multiples of threads count.\n");
671 return -1;
672 }
673
674 if (ms_setting.win_size % UNIT_ITEMS_COUNT != 0)
675 {
676 fprintf(stderr, "Window size must be the multiples of 1024.\n\n");
677 return -1;
678 }
679
680 return EXIT_SUCCESS;
681 } /* ms_check_para */
682
683
684 /* initialize the statistic structure */
685 static void ms_statistic_init()
686 {
687 pthread_mutex_init(&ms_statistic.stat_mutex, NULL);
688 ms_init_stats(&ms_statistic.get_stat, "Get");
689 ms_init_stats(&ms_statistic.set_stat, "Set");
690 ms_init_stats(&ms_statistic.total_stat, "Total");
691 } /* ms_statistic_init */
692
693
694 /* initialize the global state structure */
695 static void ms_stats_init()
696 {
697 memset(&ms_stats, 0, sizeof(ms_stats_t));
698 if (ms_setting.stat_freq > 0)
699 {
700 ms_statistic_init();
701 }
702 } /* ms_stats_init */
703
704
705 /* use to output the statistic */
706 static void ms_print_statistics(int in_time)
707 {
708 int obj_size= (int)(ms_setting.avg_key_size + ms_setting.avg_val_size);
709
710 printf("\033[1;1H\033[2J\n");
711 ms_dump_format_stats(&ms_statistic.get_stat, in_time,
712 ms_setting.stat_freq, obj_size);
713 ms_dump_format_stats(&ms_statistic.set_stat, in_time,
714 ms_setting.stat_freq, obj_size);
715 ms_dump_format_stats(&ms_statistic.total_stat, in_time,
716 ms_setting.stat_freq, obj_size);
717 } /* ms_print_statistics */
718
719
720 /* used to print the states of memslap */
721 static void ms_print_memslap_stats(struct timeval *start_time,
722 struct timeval *end_time)
723 {
724 char buf[1024];
725 char *pos= buf;
726
727 pos+= snprintf(pos,
728 sizeof(buf), "cmd_get: %lu\n",
729 (unsigned long) ms_stats.cmd_get);
730 pos+= snprintf(pos,
731 sizeof(buf) - (size_t)(pos -buf),
732 "cmd_set: %lu\n",
733 (unsigned long) ms_stats.cmd_set);
734 pos+= snprintf(pos,
735 sizeof(buf) - (size_t)(pos -buf),
736 "get_misses: %lu\n",
737 (unsigned long) ms_stats.get_misses);
738
739 if (ms_setting.verify_percent > 0)
740 {
741 pos+= snprintf(pos,
742 sizeof(buf) - (size_t)(pos -buf),
743 "verify_misses: %lu\n",
744 (unsigned long) ms_stats.vef_miss);
745 pos+= snprintf(pos,
746 sizeof(buf) - (size_t)(pos -buf),
747 "verify_failed: %lu\n",
748 (unsigned long) ms_stats.vef_failed);
749 }
750
751 if (ms_setting.exp_ver_per > 0)
752 {
753 pos+= snprintf(pos,
754 sizeof(buf) - (size_t)(pos -buf),
755 "expired_get: %lu\n",
756 (unsigned long) ms_stats.exp_get);
757 pos+= snprintf(pos,
758 sizeof(buf) - (size_t)(pos -buf),
759 "unexpired_unget: %lu\n",
760 (unsigned long) ms_stats.unexp_unget);
761 }
762
763 pos+= snprintf(pos,
764 sizeof(buf) - (size_t)(pos -buf),
765 "written_bytes: %lu\n",
766 (unsigned long) ms_stats.bytes_written);
767 pos+= snprintf(pos,
768 sizeof(buf) - (size_t)(pos -buf),
769 "read_bytes: %lu\n",
770 (unsigned long) ms_stats.bytes_read);
771 pos+= snprintf(pos,
772 sizeof(buf) - (size_t)(pos -buf),
773 "object_bytes: %lu\n",
774 (unsigned long) ms_stats.obj_bytes);
775
776 if (ms_setting.udp || ms_setting.facebook_test)
777 {
778 pos+= snprintf(pos,
779 sizeof(buf) - (size_t)(pos -buf),
780 "packet_disorder: %lu\n",
781 (unsigned long) ms_stats.pkt_disorder);
782 pos+= snprintf(pos,
783 sizeof(buf) - (size_t)(pos -buf),
784 "packet_drop: %lu\n",
785 (unsigned long)ms_stats.pkt_drop);
786 pos+= snprintf(pos,
787 sizeof(buf) - (size_t)(pos -buf),
788 "udp_timeout: %lu\n",
789 (unsigned long)ms_stats.udp_timeout);
790 }
791
792 if (ms_setting.stat_freq > 0)
793 {
794 ms_dump_stats(&ms_statistic.get_stat);
795 ms_dump_stats(&ms_statistic.set_stat);
796 ms_dump_stats(&ms_statistic.total_stat);
797 }
798
799 int64_t time_diff= ms_time_diff(start_time, end_time);
800 pos+= snprintf(pos,
801 sizeof(buf) - (size_t)(pos -buf),
802 "\nRun time: %.1fs Ops: %llu TPS: %.0Lf Net_rate: %.1fM/s\n",
803 (double)time_diff / 1000000,
804 (unsigned long long)(ms_stats.cmd_get + ms_stats.cmd_set),
805 (ms_stats.cmd_get
806 + ms_stats.cmd_set) / ((long double)time_diff / 1000000),
807 (double)(
808 ms_stats.bytes_written
809 + ms_stats.bytes_read) / 1024 / 1024
810 / ((double)time_diff / 1000000));
811 assert(pos <= buf);
812
813 fprintf(stdout, "%s", buf);
814 fflush(stdout);
815 } /* ms_print_memslap_stats */
816
817
818 /* the loop of the main thread, wait the work threads to complete */
819 static void ms_monitor_slap_mode()
820 {
821 struct timeval start_time, end_time;
822
823 /* Wait all the threads complete initialization. */
824 pthread_mutex_lock(&ms_global.init_lock.lock);
825 while (ms_global.init_lock.count < ms_setting.nthreads)
826 {
827 pthread_cond_wait(&ms_global.init_lock.cond,
828 &ms_global.init_lock.lock);
829 }
830 pthread_mutex_unlock(&ms_global.init_lock.lock);
831
832 /* only when there is no set operation it need warm up */
833 if (ms_setting.cmd_distr[CMD_SET].cmd_prop < PROP_ERROR)
834 {
835 /* Wait all the connects complete warm up. */
836 pthread_mutex_lock(&ms_global.warmup_lock.lock);
837 while (ms_global.warmup_lock.count < ms_setting.nconns)
838 {
839 pthread_cond_wait(&ms_global.warmup_lock.cond, &ms_global.warmup_lock.lock);
840 }
841 pthread_mutex_unlock(&ms_global.warmup_lock.lock);
842 }
843 ms_global.finish_warmup= true;
844
845 /* running in "run time" mode, user specify run time */
846 if (ms_setting.run_time > 0)
847 {
848 int second= 0;
849 gettimeofday(&start_time, NULL);
850 while (1)
851 {
852 sleep(1);
853 second++;
854
855 if ((ms_setting.stat_freq > 0) && (second % ms_setting.stat_freq == 0)
856 && (ms_stats.active_conns >= ms_setting.nconns)
857 && (ms_stats.active_conns <= INT_MAX))
858 {
859 ms_print_statistics(second);
860 }
861
862 if (ms_setting.run_time <= second)
863 {
864 ms_global.time_out= true;
865 break;
866 }
867
868 /* all connections disconnect */
869 if ((second > 5) && (ms_stats.active_conns == 0))
870 {
871 break;
872 }
873 }
874 gettimeofday(&end_time, NULL);
875 sleep(1); /* wait all threads clean up */
876 }
877 else
878 {
879 /* running in "execute number" mode, user specify execute number */
880 gettimeofday(&start_time, NULL);
881
882 /*
883 * We loop until we know that all connects have cleaned up.
884 */
885 pthread_mutex_lock(&ms_global.run_lock.lock);
886 while (ms_global.run_lock.count < ms_setting.nconns)
887 {
888 pthread_cond_wait(&ms_global.run_lock.cond, &ms_global.run_lock.lock);
889 }
890 pthread_mutex_unlock(&ms_global.run_lock.lock);
891
892 gettimeofday(&end_time, NULL);
893 }
894
895 ms_print_memslap_stats(&start_time, &end_time);
896 } /* ms_monitor_slap_mode */
897
898
899 /* the main function */
900 int main(int argc, char *argv[])
901 {
902 srandom((unsigned int)time(NULL));
903 ms_global_struct_init();
904
905 /* initialization */
906 ms_setting_init_pre();
907 ms_options_parse(argc, argv);
908 if (ms_check_para())
909 {
910 ms_help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION);
911 exit(1);
912 }
913 ms_setting_init_post();
914 ms_stats_init();
915 ms_thread_init();
916
917 /* waiting work thread complete its task */
918 ms_monitor_slap_mode();
919
920 /* clean up */
921 ms_thread_cleanup();
922 ms_global_struct_destroy();
923 ms_setting_cleanup();
924
925 return EXIT_SUCCESS;
926 } /* main */