bench_fwrite.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. #ifdef HAVE_CONFIG_H
  2. #include "config.h"
  3. #endif
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <sys/time.h>
  8. #include <pthread.h>
  9. #include <unistd.h>
  10. #include <log4c/defs.h>
  11. #ifdef HAVE_GETOPT_H
  12. #include <getopt.h>
  13. #endif
  14. extern char *optarg;
  15. extern int optind, opterr, optopt;
  16. /******************************************************************************/
  17. #define MAX_NUM_THREADS 100
  18. #define MSG_SIZE 128
  19. #define NUM_MSGS 16
  20. #define FILENAME "/var/opt/bench_fwrite.out"
  21. #ifdef OLD_VARIADIC_MACRO
  22. #define bench_log(args...) fprintf(stderr, args)
  23. #else
  24. #define bench_log(...) fprintf(stderr, __VA_ARGS__)
  25. #endif /* OLD_VARIADIC_MACRO */
  26. #define USAGE "This program is a log4c developer tool used to compare fwrite() performance against fprintf()\n\n" \
  27. "bench_fwrite [-f] [-n<num msgs] [-w] [-b<buffer size>]\n" \
  28. " [-t<num threads>] [-m<buffer mode> [-s<msg size>]\n" \
  29. " -f use a file rather than stdout--goes to /var/opt/bench_fwrite.out\n" \
  30. " -w use fwrite rather than fprintf\n" \
  31. " -b<buffer size> if not specified defaults to using system buffer.\n" \
  32. " if specified as zero we do setbuf NULL\n" \
  33. " if non zero we do setvbuf to that value rounded up\n" \
  34. " to the next highest BUFSIZ\n" \
  35. " -m if 1 then use IOFBF mode, otherwise use IOLBF\n" \
  36. " -p Add an sprintf() of the test string--this is usually required to format the \n" \
  37. " buffer passed to fwrite, so it's a more realistic comparison to use this\n" \
  38. "\n" \
  39. " eg. 'bench_fwrite -s256 -f -n1000000'\n" \
  40. "measures the time to write a million strings of length 256 to a file using fprintf() with the default system buffer\n" \
  41. "while 'bench_fwrite -s256 -f -n1000000 -w'\n" \
  42. "does the same thing but using fwrite()\n"
  43. /******************************************************************************/
  44. char *g_msgbuf = NULL;
  45. const char *g_outfilename = FILENAME;
  46. long g_num_msgs = NUM_MSGS;
  47. int g_usefile = 0;
  48. int g_usefwrite = 0;
  49. FILE *g_fp = NULL;
  50. int g_usebuffer = 1;
  51. int g_usemybuffer = 0;
  52. size_t g_mybufsize = 0;
  53. size_t g_mybufadjustedsize = 0;
  54. char *g_myfilebuffer = NULL;
  55. int g_numthreads = 1;
  56. int g_bufmode = 1; /* 1==full , ow. line*/
  57. long g_msgsize = MSG_SIZE;
  58. char g_tmpbuf[10*1024];
  59. int g_add_sprintf_to_fwrite = 0;
  60. /******************************************************************************/
  61. static char *make_msgbuf(long msgsize);
  62. static void bench_init( int start /* non-zero for start, 0 for exit */);
  63. static void *thread_work(void *arg);
  64. unsigned long long gettimestamp_milis(void);
  65. /******************************************************************************/
  66. static void bench_init(int start) {
  67. if (g_usefile) {
  68. if ( start) {
  69. bench_log(" Writing to file '%s'\n", g_outfilename);
  70. g_fp = fopen( g_outfilename, "w+");
  71. if ( g_fp == NULL){
  72. bench_log("Failed to open '%s' for writing\n", g_outfilename);
  73. exit(1);
  74. }
  75. if ( g_usebuffer) {
  76. if ( g_usemybuffer) {
  77. bench_log(" Using my buffer of adjusted size %lu, mode '%s'\n",
  78. g_mybufadjustedsize, (g_bufmode == 1 ? "_IOFBF":"_IOLBF") );
  79. g_myfilebuffer = (char *)malloc(g_mybufadjustedsize);
  80. setvbuf(g_fp, g_myfilebuffer, (g_bufmode == 1 ? _IOFBF:_IOLBF),
  81. g_mybufadjustedsize );
  82. } else {
  83. bench_log(" Using system buffer of size %d\n", BUFSIZ);
  84. }
  85. } else {
  86. bench_log(" Unbuffered output\n");
  87. setbuf(g_fp, NULL); /* unbuffered */
  88. }
  89. } else {
  90. bench_log(" Closing file '%s'\n", g_outfilename);
  91. fclose(g_fp);
  92. }
  93. } else {
  94. if ( start ) {
  95. bench_log( " Writing to 'stdout'\n");
  96. g_fp = stdout;
  97. }
  98. }
  99. if ( g_usefwrite ) {
  100. if ( start ){
  101. bench_log( " Using fwrite\n");
  102. if (g_add_sprintf_to_fwrite){
  103. bench_log( " Adding sprintf of msg to help compare with fprintf\n");
  104. }else{
  105. bench_log( " fwite'ing directly from a buffer--no printf required\n");
  106. }
  107. }
  108. } else {
  109. if ( start ){
  110. bench_log( " Using fprintf\n");
  111. }
  112. }
  113. }
  114. /******************************************************************************/
  115. static char *make_msgbuf(long msgsize){
  116. int i = 0;
  117. char *s = (char *)calloc(msgsize, sizeof(char));
  118. i = 0;
  119. while(i < msgsize-1) {
  120. s[i] = 'm';
  121. i++;
  122. }
  123. return(s);
  124. }
  125. /******************************************************************************/
  126. static inline void bench_dowrite(FILE *fp, char *msgbuf, size_t buflen){
  127. if ( !g_usefwrite ) {
  128. /* Don't need the len, it's a string */
  129. fprintf(fp, "%s\n", msgbuf);
  130. } else {
  131. /* use fwrite */
  132. /* bench_log("wrting using fwrite\n");*/
  133. /* sprintf here to try to make it comparable
  134. to fprintf
  135. */
  136. if (g_add_sprintf_to_fwrite){
  137. sprintf(g_tmpbuf, "%s\n", msgbuf);
  138. }
  139. fwrite(msgbuf, sizeof(char), buflen, fp);
  140. }
  141. }
  142. /******************************************************************************/
  143. void getopts(int argc, char **argv){
  144. char c;
  145. if ( argc == 1) {
  146. bench_log(USAGE);
  147. exit(1);
  148. }
  149. while ((c = getopt(argc, argv, "fn:wb:t:m:s:hp")) != -1) {
  150. switch(c) {
  151. case 'f':
  152. g_usefile = 1;
  153. /*printf("appender is '%s'\n",appender );*/
  154. break;
  155. case 'p':
  156. g_add_sprintf_to_fwrite = 1;
  157. /*printf("appender is '%s'\n",appender );*/
  158. break;
  159. case 'm':
  160. g_bufmode = atoi(optarg);
  161. /*printf("appender is '%s'\n",appender );*/
  162. break;
  163. case 'n':
  164. g_num_msgs = atol(optarg);
  165. /*printf("priority is '%s'\n",priority );*/
  166. break;
  167. case 't':
  168. g_numthreads = atoi(optarg);
  169. if ( g_numthreads <= 0 ) {
  170. g_numthreads = 1;
  171. } else if ( g_numthreads > MAX_NUM_THREADS){
  172. g_numthreads = MAX_NUM_THREADS;
  173. }
  174. /*printf("priority is '%s'\n",priority );*/
  175. break;
  176. case 'w':
  177. g_usefwrite = 1;
  178. /*printf("priority is '%s'\n",priority );*/
  179. break;
  180. case 's':
  181. g_msgsize = atol(optarg);
  182. /*printf("priority is '%s'\n",priority );*/
  183. break;
  184. case 'b':
  185. g_mybufsize = atol(optarg);
  186. if ( g_mybufsize == 0 ) {
  187. g_usebuffer = 0; /* turn off buffering completely */
  188. } else {
  189. g_usemybuffer = 1;
  190. g_mybufadjustedsize = ((BUFSIZ + g_mybufsize)/BUFSIZ)*BUFSIZ;
  191. }
  192. /*printf("priority is '%s'\n",priority );*/
  193. break;
  194. case 'h':
  195. bench_log(USAGE);
  196. exit(1);
  197. break;
  198. }
  199. }
  200. bench_log(" Writing %ld message(s) of length %ld\n",
  201. g_num_msgs,g_msgsize);
  202. }
  203. static void *thread_work(void *arg){
  204. /* int tid= *((int *)arg); */
  205. int msgnum = 0;
  206. /* bench_log("In thread %d\n", tid); */
  207. while( msgnum < g_num_msgs){
  208. bench_dowrite(g_fp, g_msgbuf, MSG_SIZE);
  209. msgnum++;
  210. }
  211. return(NULL);
  212. }
  213. unsigned long long gettimestamp_milis(){
  214. struct timeval time;
  215. unsigned long long ticks;
  216. (void)gettimeofday(&time, NULL);
  217. ticks = (unsigned long long)time.tv_sec * 1000; /* that's in milliseconds */
  218. ticks += (unsigned long long)time.tv_usec / 1000; /* so's that */
  219. return ticks;
  220. }
  221. /******************************************************************************/
  222. int main(int argc, char **argv){
  223. int i = 0;
  224. unsigned long long start, end, delta;
  225. pthread_t tid[MAX_NUM_THREADS];
  226. bench_log("Welcome to %s:\n\n", argv[0]);
  227. getopts(argc, argv);
  228. bench_init(1 /* start */);
  229. g_msgbuf = make_msgbuf(g_msgsize);
  230. if ( g_msgsize < 5 ) {
  231. bench_log(" Ridiculously short message %ld--exiting\n",
  232. g_msgsize);
  233. exit(1);
  234. }
  235. bench_log(" Starting %d thread(s)\n", g_numthreads);
  236. start = gettimestamp_milis();
  237. for ( i = 0; i < g_numthreads; i++)
  238. pthread_create(&tid[i], NULL, thread_work,
  239. (void *)&i);
  240. for ( i = 0; i < g_numthreads; i++)
  241. pthread_join(tid[i], NULL);
  242. end = gettimestamp_milis();
  243. delta = (end - start);
  244. #ifdef _WIN32
  245. bench_log( "\n Time = %I64d milisec\n", delta);
  246. #else
  247. bench_log( "\n Time = %lld milisec\n", delta);
  248. #endif
  249. bench_init(0);
  250. return(0);
  251. }