libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

benchmark.c (5720B)


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