[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r15863 - in libmicrohttpd: . src/testcurl
From: |
gnunet |
Subject: |
[GNUnet-SVN] r15863 - in libmicrohttpd: . src/testcurl |
Date: |
Thu, 7 Jul 2011 10:25:55 +0200 |
Author: grothoff
Date: 2011-07-07 10:25:55 +0200 (Thu, 07 Jul 2011)
New Revision: 15863
Added:
libmicrohttpd/src/testcurl/gauger.h
libmicrohttpd/src/testcurl/perf_get.c
libmicrohttpd/src/testcurl/perf_get_concurrent.c
Modified:
libmicrohttpd/ChangeLog
libmicrohttpd/configure.ac
libmicrohttpd/src/testcurl/Makefile.am
Log:
adding perf measurements
Modified: libmicrohttpd/ChangeLog
===================================================================
--- libmicrohttpd/ChangeLog 2011-07-07 08:23:46 UTC (rev 15862)
+++ libmicrohttpd/ChangeLog 2011-07-07 08:25:55 UTC (rev 15863)
@@ -1,3 +1,9 @@
+Thu Jul 7 10:24:20 CEST 2011
+ Adding performance measurements. -CG
+
+Thu Jun 23 14:21:13 CEST 2011
+ Releasing libmicrohttpd 0.9.12. -CG
+
Wed Jun 22 14:32:23 CEST 2011
Force closing connection if either the client asked it or
if the response contains 'Connection: close' (so far,
Modified: libmicrohttpd/configure.ac
===================================================================
--- libmicrohttpd/configure.ac 2011-07-07 08:23:46 UTC (rev 15862)
+++ libmicrohttpd/configure.ac 2011-07-07 08:25:55 UTC (rev 15863)
@@ -81,46 +81,55 @@
AC_DEFINE_UNQUOTED(OSX,1,[This is an OS X system])
CFLAGS="-no-cpp-precomp -fno-common $CFLAGS"
AM_CONDITIONAL(HAVE_GNU_LD, false)
+ AM_CONDITIONAL(HAVE_W32, false)
;;
linux*)
AC_DEFINE_UNQUOTED(LINUX,1,[This is a Linux system])
AM_CONDITIONAL(HAVE_GNU_LD, true)
+ AM_CONDITIONAL(HAVE_W32, false)
;;
freebsd*)
AC_DEFINE_UNQUOTED(SOMEBSD,1,[This is a BSD system])
AC_DEFINE_UNQUOTED(FREEBSD,1,[This is a FreeBSD system])
AM_CONDITIONAL(HAVE_GNU_LD, true)
+ AM_CONDITIONAL(HAVE_W32, false)
CFLAGS="-D_THREAD_SAFE $CFLAGS"
;;
openbsd*)
AC_DEFINE_UNQUOTED(SOMEBSD,1,[This is a BSD system])
AC_DEFINE_UNQUOTED(OPENBSD,1,[This is an OpenBSD system])
AM_CONDITIONAL(HAVE_GNU_LD, true)
+ AM_CONDITIONAL(HAVE_W32, false)
;;
netbsd*)
AC_DEFINE_UNQUOTED(SOMEBSD,1,[This is a BSD system])
AC_DEFINE_UNQUOTED(NETBSD,1,[This is a NetBSD system])
AM_CONDITIONAL(HAVE_GNU_LD, true)
+ AM_CONDITIONAL(HAVE_W32, false)
;;
*solaris*)
AC_DEFINE_UNQUOTED(SOLARIS,1,[This is a Solaris system])
AC_DEFINE_UNQUOTED(_REENTRANT,1,[Need with solaris or errno doesnt work])
AM_CONDITIONAL(HAVE_GNU_LD, false)
+ AM_CONDITIONAL(HAVE_W32, false)
LDFLAGS="$LDFLAGS -lpthread"
;;
*arm-linux*)
AC_DEFINE_UNQUOTED(LINUX,1,[This is a Linux system])
CFLAGS="-D_REENTRANT -fPIC -pipe $CFLAGS"
AM_CONDITIONAL(HAVE_GNU_LD, true)
+ AM_CONDITIONAL(HAVE_W32, false)
;;
*cygwin*)
AC_DEFINE_UNQUOTED(CYGWIN,1,[This is a Cygwin system])
- AM_CONDITIONAL(HAVE_GNU_LD, false)
+ AM_CONDITIONAL(HAVE_GNU_LD, false)
+ AM_CONDITIONAL(HAVE_W32, false)
LDFLAGS="$LDFLAGS -no-undefined"
;;
*mingw*)
AC_DEFINE_UNQUOTED(MINGW,1,[This is a MinGW system])
AC_DEFINE_UNQUOTED(WINDOWS,1,[This is a Windows system])
+ AM_CONDITIONAL(HAVE_W32, true)
LDFLAGS="$LDFLAGS -no-undefined -Wl,--export-all-symbols -lws2_32"
AM_CONDITIONAL(HAVE_GNU_LD, true)
# check if PlibC is available
@@ -133,11 +142,13 @@
*openedition*)
AC_DEFINE_UNQUOTED(OS390,1,[This is a OS/390 system])
AM_CONDITIONAL(HAVE_GNU_LD, false)
+ AM_CONDITIONAL(HAVE_W32, false)
;;
*)
AC_MSG_RESULT(Unrecognised OS $host_os)
AC_DEFINE_UNQUOTED(OTHEROS,1,[Some strange OS])
AM_CONDITIONAL(HAVE_GNU_LD, false)
+ AM_CONDITIONAL(HAVE_W32, false)
;;
esac
Modified: libmicrohttpd/src/testcurl/Makefile.am
===================================================================
--- libmicrohttpd/src/testcurl/Makefile.am 2011-07-07 08:23:46 UTC (rev
15862)
+++ libmicrohttpd/src/testcurl/Makefile.am 2011-07-07 08:25:55 UTC (rev
15863)
@@ -19,6 +19,10 @@
-I$(top_srcdir)/src/include \
$(LIBCURL_CPPFLAGS)
+if !HAVE_W32
+PERF_GET_CONCURRENT=perf_get_concurrent
+endif
+
check_PROGRAMS = \
daemontest_get \
daemontest_get_sendfile \
@@ -43,7 +47,10 @@
daemontest_put_chunked \
daemontest_iplimit11 \
daemontest_termination \
- daemontest_timeout
+ daemontest_timeout \
+ perf_get $(PERF_GET_CONCURRENT)
+
+
noinst_PROGRAMS = \
daemon_options_test
@@ -70,6 +77,20 @@
$(top_builddir)/src/daemon/libmicrohttpd.la \
@LIBCURL@
+perf_get_SOURCES = \
+ perf_get.c \
+ gauger.h
+perf_get_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
+perf_get_concurrent_SOURCES = \
+ perf_get_concurrent.c \
+ gauger.h
+perf_get_concurrent_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la \
+ @LIBCURL@
+
daemontest_digestauth_SOURCES = \
daemontest_digestauth.c
daemontest_digestauth_LDADD = \
Added: libmicrohttpd/src/testcurl/gauger.h
===================================================================
--- libmicrohttpd/src/testcurl/gauger.h (rev 0)
+++ libmicrohttpd/src/testcurl/gauger.h 2011-07-07 08:25:55 UTC (rev 15863)
@@ -0,0 +1,86 @@
+/** ---------------------------------------------------------------------------
+ * This software is in the public domain, furnished "as is", without technical
+ * support, and with no warranty, express or implied, as to its usefulness for
+ * any purpose.
+ *
+ * gauger.h
+ * Interface for C programs to log remotely to a gauger server
+ *
+ * Author: Bartlomiej Polot
+ * -------------------------------------------------------------------------*/
+#ifndef __GAUGER_H__
+#define __GAUGER_H__
+
+#ifndef WINDOWS
+
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/wait.h>
+
+#define GAUGER(category, counter, value, unit)\
+{\
+ const char * __gauger_v[10]; \
+ char __gauger_s[32];\
+ pid_t __gauger_p;\
+ if(!(__gauger_p=fork())){\
+ if(!fork()){ \
+ sprintf(__gauger_s,"%Lf", (long double) (value));\
+ __gauger_v[0] = "gauger";\
+ __gauger_v[1] = "-n";\
+ __gauger_v[2] = counter; \
+ __gauger_v[3] = "-d";\
+ __gauger_v[4] = __gauger_s;\
+ __gauger_v[5] = "-u";\
+ __gauger_v[6] = unit; \
+ __gauger_v[7] = "-c";\
+ __gauger_v[8] = category; \
+ __gauger_v[9] = (char *)NULL;\
+ execvp("gauger", (char*const*) __gauger_v); \
+ _exit(1);\
+ }else{\
+ _exit(0);\
+ }\
+ }else{\
+ waitpid(__gauger_p,NULL,0);\
+ }\
+}
+
+#define GAUGER_ID(category, counter, value, unit, id)\
+{\
+ char* __gauger_v[12];\
+ char __gauger_s[32];\
+ pid_t __gauger_p;\
+ if(!(__gauger_p=fork())){\
+ if(!fork()){\
+ sprintf(__gauger_s,"%Lf", (long double) (value));\
+ __gauger_v[0] = "gauger";\
+ __gauger_v[1] = "-n";\
+ __gauger_v[2] = counter;\
+ __gauger_v[3] = "-d";\
+ __gauger_v[4] = __gauger_s;\
+ __gauger_v[5] = "-u";\
+ __gauger_v[6] = unit;\
+ __gauger_v[7] = "-i";\
+ __gauger_v[8] = id;\
+ __gauger_v[9] = "-c";\
+ __gauger_v[10] = category;\
+ __gauger_v[11] = (char *)NULL;\
+ execvp("gauger",__gauger_v);\
+ perror("gauger");\
+ _exit(1);\
+ }else{\
+ _exit(0);\
+ }\
+ }else{\
+ waitpid(__gauger_p,NULL,0);\
+ }\
+}
+
+#else
+
+#define GAUGER_ID(category, counter, value, unit, id) {}
+#define GAUGER(category, counter, value, unit) {}
+
+#endif // WINDOWS
+
+#endif
Added: libmicrohttpd/src/testcurl/perf_get.c
===================================================================
--- libmicrohttpd/src/testcurl/perf_get.c (rev 0)
+++ libmicrohttpd/src/testcurl/perf_get.c 2011-07-07 08:25:55 UTC (rev
15863)
@@ -0,0 +1,491 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007, 2009, 2011 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file perf_get.c
+ * @brief benchmark simple GET operations (sequential access).
+ * Note that we run libcurl in the same process at the
+ * same time, so the execution time given is the combined
+ * time for both MHD and libcurl; it is quite possible
+ * that more time is spend with libcurl than with MHD,
+ * so the performance scores calculated with this code
+ * should NOT be used to compare with other HTTP servers
+ * (since MHD is actually better); only the relative
+ * scores between MHD versions are meaningful.
+ * Furthermore, this code ONLY tests MHD processing
+ * a single request at a time. This is again
+ * not universally meaningful (i.e. when comparing
+ * multithreaded vs. single-threaded or select/poll).
+ * @author Christian Grothoff
+ */
+
+#include "MHD_config.h"
+#include "platform.h"
+#include <curl/curl.h>
+#include <microhttpd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "gauger.h"
+
+#ifndef WINDOWS
+#include <unistd.h>
+#include <sys/socket.h>
+#endif
+
+/**
+ * How many rounds of operations do we do for each
+ * test?
+ */
+#define ROUNDS 500
+
+/**
+ * Do we use HTTP 1.1?
+ */
+static int oneone;
+
+/**
+ * Response to return (re-used).
+ */
+static struct MHD_Response *response;
+
+/**
+ * Time this round was started.
+ */
+static unsigned long long start_time;
+
+
+/**
+ * Get the current timestamp
+ *
+ * @return current time in ms
+ */
+static unsigned long long
+now ()
+{
+ struct timeval tv;
+
+ GETTIMEOFDAY (&tv, NULL);
+ return (((unsigned long long) tv.tv_sec * 1000LL) +
+ ((unsigned long long) tv.tv_usec / 1000LL));
+}
+
+
+/**
+ * Start the timer.
+ */
+static void
+start_timer()
+{
+ start_time = now ();
+}
+
+
+/**
+ * Stop the timer and report performance
+ *
+ * @param desc description of the threading mode we used
+ */
+static void
+stop (const char *desc)
+{
+ double rps = ((double) (ROUNDS * 1000)) / ((double) (now() - start_time));
+
+ fprintf (stderr,
+ "Sequential GETs using %s: %f %s\n",
+ desc,
+ rps,
+ "requests/s");
+ GAUGER (desc,
+ "Sequential GETs",
+ rps,
+ "requests/s");
+}
+
+
+struct CBC
+{
+ char *buf;
+ size_t pos;
+ size_t size;
+};
+
+
+static size_t
+copyBuffer (void *ptr,
+ size_t size, size_t nmemb,
+ void *ctx)
+{
+ struct CBC *cbc = ctx;
+
+ if (cbc->pos + size * nmemb > cbc->size)
+ return 0; /* overflow */
+ memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
+ cbc->pos += size * nmemb;
+ return size * nmemb;
+}
+
+static int
+ahc_echo (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data, size_t *upload_data_size,
+ void **unused)
+{
+ static int ptr;
+ const char *me = cls;
+ int ret;
+
+ if (0 != strcmp (me, method))
+ return MHD_NO; /* unexpected method */
+ if (&ptr != *unused)
+ {
+ *unused = &ptr;
+ return MHD_YES;
+ }
+ *unused = NULL;
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ if (ret == MHD_NO)
+ abort ();
+ return ret;
+}
+
+
+static int
+testInternalGet (int poll_flag)
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLcode errornum;
+ unsigned int i;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG | poll_flag,
+ 11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+ if (d == NULL)
+ return 1;
+ start_timer ();
+ for (i=0;i<ROUNDS;i++)
+ {
+ cbc.pos = 0;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11080/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ /* NOTE: use of CONNECTTIMEOUT without also
+ setting NOSIGNAL results in really weird
+ crashes on my system!*/
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK != (errornum = curl_easy_perform (c)))
+ {
+ fprintf (stderr,
+ "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 2;
+ }
+ curl_easy_cleanup (c);
+ }
+ stop (poll_flag ? "internal poll" : "internal select");
+ MHD_stop_daemon (d);
+ if (cbc.pos != strlen ("/hello_world"))
+ return 4;
+ if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+ return 8;
+ return 0;
+}
+
+
+static int
+testMultithreadedGet (int poll_flag)
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLcode errornum;
+ unsigned int i;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG |
poll_flag,
+ 1081, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+ if (d == NULL)
+ return 16;
+ start_timer ();
+ for (i=0;i<ROUNDS;i++)
+ {
+ cbc.pos = 0;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ /* NOTE: use of CONNECTTIMEOUT without also
+ setting NOSIGNAL results in really weird
+ crashes on my system! */
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK != (errornum = curl_easy_perform (c)))
+ {
+ fprintf (stderr,
+ "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 32;
+ }
+ curl_easy_cleanup (c);
+ }
+ stop (poll_flag ? "thread with poll" : "thread with select");
+ MHD_stop_daemon (d);
+ if (cbc.pos != strlen ("/hello_world"))
+ return 64;
+ if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+ return 128;
+ return 0;
+}
+
+static int
+testMultithreadedPoolGet (int poll_flag)
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLcode errornum;
+ unsigned int i;
+
+ cbc.buf = buf;
+ cbc.size = 2048;
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG | poll_flag,
+ 1081, NULL, NULL, &ahc_echo, "GET",
+ MHD_OPTION_THREAD_POOL_SIZE, 4, MHD_OPTION_END);
+ if (d == NULL)
+ return 16;
+ start_timer ();
+ for (i=0;i<ROUNDS;i++)
+ {
+ cbc.pos = 0;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ /* NOTE: use of CONNECTTIMEOUT without also
+ setting NOSIGNAL results in really weird
+ crashes on my system!*/
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK != (errornum = curl_easy_perform (c)))
+ {
+ fprintf (stderr,
+ "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 32;
+ }
+ curl_easy_cleanup (c);
+ }
+ stop (poll_flag ? "thread pool with poll" : "thread pool with select");
+ MHD_stop_daemon (d);
+ if (cbc.pos != strlen ("/hello_world"))
+ return 64;
+ if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+ return 128;
+ return 0;
+}
+
+static int
+testExternalGet ()
+{
+ struct MHD_Daemon *d;
+ CURL *c;
+ char buf[2048];
+ struct CBC cbc;
+ CURLM *multi;
+ CURLMcode mret;
+ fd_set rs;
+ fd_set ws;
+ fd_set es;
+ int max;
+ int running;
+ struct CURLMsg *msg;
+ time_t start;
+ struct timeval tv;
+ unsigned int i;
+
+ multi = NULL;
+ cbc.buf = buf;
+ cbc.size = 2048;
+ d = MHD_start_daemon (MHD_USE_DEBUG,
+ 1082, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+ if (d == NULL)
+ return 256;
+ start_timer ();
+ multi = curl_multi_init ();
+ if (multi == NULL)
+ {
+ MHD_stop_daemon (d);
+ return 512;
+ }
+ for (i=0;i<ROUNDS;i++)
+ {
+ cbc.pos = 0;
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1082/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ /* NOTE: use of CONNECTTIMEOUT without also
+ setting NOSIGNAL results in really weird
+ crashes on my system! */
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ mret = curl_multi_add_handle (multi, c);
+ if (mret != CURLM_OK)
+ {
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 1024;
+ }
+ start = time (NULL);
+ while ((time (NULL) - start < 5) && (c != NULL))
+ {
+ max = 0;
+ FD_ZERO (&rs);
+ FD_ZERO (&ws);
+ FD_ZERO (&es);
+ curl_multi_perform (multi, &running);
+ mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
+ if (mret != CURLM_OK)
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 2048;
+ }
+ if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_multi_cleanup (multi);
+ curl_easy_cleanup (c);
+ MHD_stop_daemon (d);
+ return 4096;
+ }
+ tv.tv_sec = 0;
+ tv.tv_usec = 1000;
+ select (max + 1, &rs, &ws, &es, &tv);
+ curl_multi_perform (multi, &running);
+ if (running == 0)
+ {
+ msg = curl_multi_info_read (multi, &running);
+ if (msg == NULL)
+ break;
+ if (msg->msg == CURLMSG_DONE)
+ {
+ if (msg->data.result != CURLE_OK)
+ printf ("%s failed at %s:%d: `%s'\n",
+ "curl_multi_perform",
+ __FILE__,
+ __LINE__, curl_easy_strerror (msg->data.result));
+ curl_multi_remove_handle (multi, c);
+ curl_easy_cleanup (c);
+ c = NULL;
+ }
+ }
+ MHD_run (d);
+ }
+ if (NULL != c)
+ {
+ curl_multi_remove_handle (multi, c);
+ curl_easy_cleanup (c);
+ fprintf (stderr, "Timeout!?\n");
+ }
+ }
+ stop ("external select");
+ if (multi != NULL)
+ {
+ curl_multi_cleanup (multi);
+ }
+ MHD_stop_daemon (d);
+ if (cbc.pos != strlen ("/hello_world"))
+ return 8192;
+ if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+ return 16384;
+ return 0;
+}
+
+
+int
+main (int argc, char *const *argv)
+{
+ unsigned int errorCount = 0;
+
+ oneone = NULL != strstr (argv[0], "11");
+ if (0 != curl_global_init (CURL_GLOBAL_WIN32))
+ return 2;
+ response = MHD_create_response_from_buffer (strlen ("/hello_world"),
+ "/hello_world",
+ MHD_RESPMEM_MUST_COPY);
+ errorCount += testInternalGet (0);
+ errorCount += testMultithreadedGet (0);
+ errorCount += testMultithreadedPoolGet (0);
+ errorCount += testExternalGet ();
+ errorCount += testInternalGet (MHD_USE_POLL);
+ errorCount += testMultithreadedGet (MHD_USE_POLL);
+ errorCount += testMultithreadedPoolGet (MHD_USE_POLL);
+ MHD_destroy_response (response);
+ if (errorCount != 0)
+ fprintf (stderr, "Error (code: %u)\n", errorCount);
+ curl_global_cleanup ();
+ return errorCount != 0; /* 0 == pass */
+}
Added: libmicrohttpd/src/testcurl/perf_get_concurrent.c
===================================================================
--- libmicrohttpd/src/testcurl/perf_get_concurrent.c
(rev 0)
+++ libmicrohttpd/src/testcurl/perf_get_concurrent.c 2011-07-07 08:25:55 UTC
(rev 15863)
@@ -0,0 +1,338 @@
+/*
+ This file is part of libmicrohttpd
+ (C) 2007, 2009, 2011 Christian Grothoff
+
+ libmicrohttpd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libmicrohttpd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libmicrohttpd; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file perf_get_concurrent.c
+ * @brief benchmark concurrent GET operations
+ * Note that we run libcurl on the machine at the
+ * same time, so the execution time may be influenced
+ * by the concurrent activity; it is quite possible
+ * that more time is spend with libcurl than with MHD,
+ * so the performance scores calculated with this code
+ * should NOT be used to compare with other HTTP servers
+ * (since MHD is actually better); only the relative
+ * scores between MHD versions are meaningful.
+ * @author Christian Grothoff
+ */
+
+#include "MHD_config.h"
+#include "platform.h"
+#include <curl/curl.h>
+#include <microhttpd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "gauger.h"
+
+/**
+ * How many rounds of operations do we do for each
+ * test (total number of requests will be ROUNDS * PAR).
+ */
+#define ROUNDS 500
+
+/**
+ * How many requests do we do in parallel?
+ */
+#define PAR 4
+
+/**
+ * Do we use HTTP 1.1?
+ */
+static int oneone;
+
+/**
+ * Response to return (re-used).
+ */
+static struct MHD_Response *response;
+
+/**
+ * Time this round was started.
+ */
+static unsigned long long start_time;
+
+
+/**
+ * Get the current timestamp
+ *
+ * @return current time in ms
+ */
+static unsigned long long
+now ()
+{
+ struct timeval tv;
+
+ GETTIMEOFDAY (&tv, NULL);
+ return (((unsigned long long) tv.tv_sec * 1000LL) +
+ ((unsigned long long) tv.tv_usec / 1000LL));
+}
+
+
+/**
+ * Start the timer.
+ */
+static void
+start_timer()
+{
+ start_time = now ();
+}
+
+
+/**
+ * Stop the timer and report performance
+ *
+ * @param desc description of the threading mode we used
+ */
+static void
+stop (const char *desc)
+{
+ double rps = ((double) (PAR * ROUNDS * 1000)) / ((double) (now() -
start_time));
+
+ fprintf (stderr,
+ "Parallel GETs using %s: %f %s\n",
+ desc,
+ rps,
+ "requests/s");
+ GAUGER (desc,
+ "Parallel GETs",
+ rps,
+ "requests/s");
+}
+
+
+static size_t
+copyBuffer (void *ptr,
+ size_t size, size_t nmemb,
+ void *ctx)
+{
+ return size * nmemb;
+}
+
+static int
+ahc_echo (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data, size_t *upload_data_size,
+ void **unused)
+{
+ static int ptr;
+ const char *me = cls;
+ int ret;
+
+ if (0 != strcmp (me, method))
+ return MHD_NO; /* unexpected method */
+ if (&ptr != *unused)
+ {
+ *unused = &ptr;
+ return MHD_YES;
+ }
+ *unused = NULL;
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ if (ret == MHD_NO)
+ abort ();
+ return ret;
+}
+
+
+static pid_t
+do_gets ()
+{
+ pid_t ret;
+ CURL *c;
+ CURLcode errornum;
+ unsigned int i;
+ unsigned int j;
+ pid_t par[PAR];
+
+ ret = fork ();
+ if (ret == -1) abort ();
+ if (ret != 0)
+ return ret;
+ for (j=0;j<PAR;j++)
+ {
+ par[j] = fork ();
+ if (par[j] == 0)
+ {
+ for (i=0;i<ROUNDS;i++)
+ {
+ c = curl_easy_init ();
+ curl_easy_setopt (c, CURLOPT_URL,
"http://localhost:1081/hello_world");
+ curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer);
+ curl_easy_setopt (c, CURLOPT_WRITEDATA, NULL);
+ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+ if (oneone)
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION,
CURL_HTTP_VERSION_1_1);
+ else
+ curl_easy_setopt (c, CURLOPT_HTTP_VERSION,
CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+ /* NOTE: use of CONNECTTIMEOUT without also
+ setting NOSIGNAL results in really weird
+ crashes on my system! */
+ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+ if (CURLE_OK != (errornum = curl_easy_perform (c)))
+ {
+ fprintf (stderr,
+ "curl_easy_perform failed: `%s'\n",
+ curl_easy_strerror (errornum));
+ curl_easy_cleanup (c);
+ _exit (1);
+ }
+ curl_easy_cleanup (c);
+ }
+ _exit (0);
+ }
+ }
+ for (j=0;j<PAR;j++)
+ waitpid (par[j], NULL, 0);
+ _exit (0);
+}
+
+
+static void
+join_gets (pid_t pid)
+{
+ int status;
+
+ status = 1;
+ waitpid (pid, &status, 0);
+ if (0 != status)
+ abort ();
+}
+
+
+static int
+testInternalGet (int poll_flag)
+{
+ struct MHD_Daemon *d;
+
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG | poll_flag,
+ 1081, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+ if (d == NULL)
+ return 1;
+ start_timer ();
+ join_gets (do_gets ());
+ stop (poll_flag ? "internal poll" : "internal select");
+ MHD_stop_daemon (d);
+ return 0;
+}
+
+
+static int
+testMultithreadedGet (int poll_flag)
+{
+ struct MHD_Daemon *d;
+
+ d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG |
poll_flag,
+ 1081, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+ if (d == NULL)
+ return 16;
+ start_timer ();
+ join_gets (do_gets ());
+ stop (poll_flag ? "thread with poll" : "thread with select");
+ MHD_stop_daemon (d);
+ return 0;
+}
+
+static int
+testMultithreadedPoolGet (int poll_flag)
+{
+ struct MHD_Daemon *d;
+
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG | poll_flag,
+ 1081, NULL, NULL, &ahc_echo, "GET",
+ MHD_OPTION_THREAD_POOL_SIZE, 4, MHD_OPTION_END);
+ if (d == NULL)
+ return 16;
+ start_timer ();
+ join_gets (do_gets ());
+ stop (poll_flag ? "thread pool with poll" : "thread pool with select");
+ MHD_stop_daemon (d);
+ return 0;
+}
+
+static int
+testExternalGet ()
+{
+ struct MHD_Daemon *d;
+ pid_t pid;
+ fd_set rs;
+ fd_set ws;
+ fd_set es;
+ int max;
+ struct timeval tv;
+ unsigned MHD_LONG_LONG tt;
+ int tret;
+
+ d = MHD_start_daemon (MHD_USE_DEBUG,
+ 1081, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+ if (d == NULL)
+ return 256;
+ start_timer ();
+ pid = do_gets ();
+ while (0 == waitpid (pid, NULL, WNOHANG))
+ {
+ max = 0;
+ FD_ZERO (&rs);
+ FD_ZERO (&ws);
+ FD_ZERO (&es);
+ if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
+ {
+ MHD_stop_daemon (d);
+ return 4096;
+ }
+ tret = MHD_get_timeout (d, &tt);
+ if (MHD_YES != tret) tt = 1;
+ tv.tv_sec = tt / 1000;
+ tv.tv_usec = 1000 * (tt % 1000);
+ select (max + 1, &rs, &ws, &es, &tv);
+ MHD_run (d);
+ }
+ stop ("external select");
+ MHD_stop_daemon (d);
+ return 0;
+}
+
+
+int
+main (int argc, char *const *argv)
+{
+ unsigned int errorCount = 0;
+
+ oneone = NULL != strstr (argv[0], "11");
+ if (0 != curl_global_init (CURL_GLOBAL_WIN32))
+ return 2;
+ response = MHD_create_response_from_buffer (strlen ("/hello_world"),
+ "/hello_world",
+ MHD_RESPMEM_MUST_COPY);
+ errorCount += testInternalGet (0);
+ errorCount += testMultithreadedGet (0);
+ errorCount += testMultithreadedPoolGet (0);
+ errorCount += testExternalGet ();
+ errorCount += testInternalGet (MHD_USE_POLL);
+ errorCount += testMultithreadedGet (MHD_USE_POLL);
+ errorCount += testMultithreadedPoolGet (MHD_USE_POLL);
+ MHD_destroy_response (response);
+ if (errorCount != 0)
+ fprintf (stderr, "Error (code: %u)\n", errorCount);
+ curl_global_cleanup ();
+ return errorCount != 0; /* 0 == pass */
+}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r15863 - in libmicrohttpd: . src/testcurl,
gnunet <=