Home | History | Annotate | Download | only in examples
      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