1 /* 2 This file is part of libmicrohttpd 3 Copyright (C) 2007, 2013 Christian Grothoff (and other contributing authors) 4 5 This library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 This library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with this library; if not, write to the Free Software 17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 /** 20 * @file benchmark.c 21 * @brief minimal code to benchmark MHD GET performance 22 * @author Christian Grothoff 23 */ 24 25 #include "platform.h" 26 #include <microhttpd.h> 27 28 #if defined(CPU_COUNT) && (CPU_COUNT+0) < 2 29 #undef CPU_COUNT 30 #endif 31 #if !defined(CPU_COUNT) 32 #define CPU_COUNT 2 33 #endif 34 35 #define PAGE "<html><head><title>libmicrohttpd demo</title></head><body>libmicrohttpd demo</body></html>" 36 37 38 #define SMALL (1024 * 128) 39 40 /** 41 * Number of threads to run in the thread pool. Should (roughly) match 42 * the number of cores on your system. 43 */ 44 #define NUMBER_OF_THREADS CPU_COUNT 45 46 static unsigned int small_deltas[SMALL]; 47 48 static struct MHD_Response *response; 49 50 51 52 /** 53 * Signature of the callback used by MHD to notify the 54 * application about completed requests. 55 * 56 * @param cls client-defined closure 57 * @param connection connection handle 58 * @param con_cls value as set by the last call to 59 * the MHD_AccessHandlerCallback 60 * @param toe reason for request termination 61 * @see MHD_OPTION_NOTIFY_COMPLETED 62 */ 63 static void 64 completed_callback (void *cls, 65 struct MHD_Connection *connection, 66 void **con_cls, 67 enum MHD_RequestTerminationCode toe) 68 { 69 struct timeval *tv = *con_cls; 70 struct timeval tve; 71 uint64_t delta; 72 73 if (NULL == tv) 74 return; 75 gettimeofday (&tve, NULL); 76 77 delta = 0; 78 if (tve.tv_usec >= tv->tv_usec) 79 delta += (tve.tv_sec - tv->tv_sec) * 1000000LL 80 + (tve.tv_usec - tv->tv_usec); 81 else 82 delta += (tve.tv_sec - tv->tv_sec) * 1000000LL 83 - tv->tv_usec + tve.tv_usec; 84 if (delta < SMALL) 85 small_deltas[delta]++; 86 else 87 fprintf (stdout, "D: %llu 1\n", (unsigned long long) delta); 88 free (tv); 89 } 90 91 92 static void * 93 uri_logger_cb (void *cls, 94 const char *uri) 95 { 96 struct timeval *tv = malloc (sizeof (struct timeval)); 97 98 if (NULL != tv) 99 gettimeofday (tv, NULL); 100 return tv; 101 } 102 103 104 static int 105 ahc_echo (void *cls, 106 struct MHD_Connection *connection, 107 const char *url, 108 const char *method, 109 const char *version, 110 const char *upload_data, size_t *upload_data_size, void **ptr) 111 { 112 if (0 != strcmp (method, "GET")) 113 return MHD_NO; /* unexpected method */ 114 return MHD_queue_response (connection, MHD_HTTP_OK, response); 115 } 116 117 118 int 119 main (int argc, char *const *argv) 120 { 121 struct MHD_Daemon *d; 122 unsigned int i; 123 124 if (argc != 2) 125 { 126 printf ("%s PORT\n", argv[0]); 127 return 1; 128 } 129 response = MHD_create_response_from_buffer (strlen (PAGE), 130 (void *) PAGE, 131 MHD_RESPMEM_PERSISTENT); 132 #if 0 133 (void) MHD_add_response_header (response, 134 MHD_HTTP_HEADER_CONNECTION, 135 "close"); 136 #endif 137 d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_SUPPRESS_DATE_NO_CLOCK 138 #if EPOLL_SUPPORT 139 | MHD_USE_EPOLL_LINUX_ONLY | MHD_USE_EPOLL_TURBO 140 #endif 141 , 142 atoi (argv[1]), 143 NULL, NULL, &ahc_echo, NULL, 144 MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 120, 145 MHD_OPTION_THREAD_POOL_SIZE, (unsigned int) NUMBER_OF_THREADS, 146 MHD_OPTION_URI_LOG_CALLBACK, &uri_logger_cb, NULL, 147 MHD_OPTION_NOTIFY_COMPLETED, &completed_callback, NULL, 148 MHD_OPTION_CONNECTION_LIMIT, (unsigned int) 1000, 149 MHD_OPTION_END); 150 if (d == NULL) 151 return 1; 152 (void) getc (stdin); 153 MHD_stop_daemon (d); 154 MHD_destroy_response (response); 155 for (i=0;i<SMALL;i++) 156 if (0 != small_deltas[i]) 157 fprintf (stdout, "D: %d %u\n", i, small_deltas[i]); 158 return 0; 159 } 160