⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 httperf.c

📁 一个WEB服务器的性能测试工具
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    httperf -- a tool for measuring web server performance    Copyright (C) 2000  Hewlett-Packard Company    Contributed by David Mosberger-Tang <davidm@hpl.hp.com>    This file is part of httperf, a web server performance measurment    tool.    This program 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 of the    License, or (at your option) any later version.    This program 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 this program; if not, write to the Free Software    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA    02111-1307 USA*//*  Fundamentals:  There are three subsystems to httperf:  1) The load generator which determines what URI is fetched next.  2) The core engine that handles the mechanics of issuing a request.  3) The instrumentation infrastructure that measures various aspects  of the transaction(s).  Since there is considerable potential variation in all three, it  seems like an event-based approach might be ideal in tying the three  together.  Ideally, it should be possible to write a new load  generator without modifications to the other subsystems.  Similarly,  it should be possible to add instrumentation without requiring  changes to the load generator or http engine.  Axioms:	- The only point at which the client will fall back is if	  the client itself is overloaded.  There is no point trying	  to fix up this case---simply declare defeat and abort the	  test. */#include "config.h"#include <ctype.h>#include <errno.h>#include <getopt.h>#include <signal.h>#include <stdarg.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/time.h>#include <sys/resource.h>#include <core.h>#include <event.h>#include <httperf.h>#include <conn.h>#include <timer.h>#ifdef HAVE_SSL#  include <openssl/rand.h>#endif#define RATE_INTERVAL	5.0const char *prog_name;int verbose;Cmdline_Params param;Time test_time_start;Time test_time_stop;struct rusage test_rusage_start;struct rusage test_rusage_stop;size_t object_type_size[OBJ_NUM_TYPES];#ifdef HAVE_SSL  SSL_CTX *ssl_ctx;#endif#ifdef DEBUGint debug_level;#endifstatic Time perf_sample_start;static struct option longopts[] =  {    {"add-header",   required_argument, (int *) &param.additional_header, 0},    {"burst-length", required_argument, &param.burst_len,		0},    {"client",	     required_argument, (int *) &param.client,		0},    {"close-with-reset", no_argument,	&param.close_with_reset,	1},    {"debug",	     required_argument,	0,				'd'},    {"failure-status", required_argument, &param.failure_status,	0},    {"help",	     no_argument,	0,				'h'},    {"hog",	     no_argument,	&param.hog,			1},    {"http-version", required_argument, (int *) &param.http_version,	0},    {"max-connections", required_argument, &param.max_conns,		0},    {"max-piped-calls", required_argument, &param.max_piped,		0},    {"method",	     required_argument,	(int *) &param.method,		0},    {"no-host-hdr",  no_argument,	&param.no_host_hdr,		1},    {"num-calls",    required_argument, (int *) &param.num_calls,	0},    {"num-conns",    required_argument, (int *) &param.num_conns,	0},    {"period",	     required_argument,	(int *) &param.rate.mean_iat,	0},    {"port",	     required_argument, (int *) &param.port,		0},    {"print-reply",  optional_argument, &param.print_reply,		0},    {"print-request",optional_argument, &param.print_request, 		0},    {"rate",	     required_argument,	(int *) &param.rate,		0},    {"recv-buffer",  required_argument, (int *) &param.recv_buffer_size, 0},    {"retry-on-failure", no_argument,	&param.retry_on_failure,	1},    {"send-buffer",  required_argument, (int *) &param.send_buffer_size, 0},    {"server",	     required_argument, (int *) &param.server,		0},    {"server-name",  required_argument, (int *) &param.server_name,	0},    {"session-cookies", no_argument,	(int *) &param.session_cookies,	1},#ifdef HAVE_SSL    {"ssl",	     no_argument,	&param.use_ssl,			1},    {"ssl-ciphers",  required_argument, (int *) &param.ssl_cipher_list, 0},    {"ssl-no-reuse", no_argument,	&param.ssl_reuse,		0},#endif    {"think-timeout",required_argument, (int *) &param.think_timeout,	0},    {"timeout",      required_argument,	(int *) &param.timeout,		0},    {"uri",	     required_argument, (int *) &param.uri,		0},    {"verbose",	     no_argument,	0,				'v'},    {"version",	     no_argument,	0,				'V'},    {"wlog",	     required_argument, (int *) &param.wlog,            0},    {"wsess",	     required_argument, (int *) &param.wsess,		0},    {"wsesslog",     required_argument, (int *) &param.wsesslog,	0},    {"wsesspage",    required_argument, (int *) &param.wsesspage,	0},    {"wset",	     required_argument, (int *) &param.wset,		0},    {0,		     0,			0,				0}  };static voidusage (void){  printf ("Usage: %s "	  "[-hdvV] [--add-header S] [--burst-length N] [--client N/N]\n"	  "\t[--close-with-reset] [--debug N] [--failure-status N]\n"	  "\t[--help] [--hog] [--http-version S] [--max-connections N]\n"	  "\t[--max-piped-calls N] [--method S] [--no-host-hdr]\n"	  "\t[--num-calls N] [--num-conns N] [--period [d|u|e]T1[,T2]]\n"	  "\t[--port N] "	  "[--print-reply [header|body]] [--print-request [header|body]]\n"	  "\t[--rate X] [--recv-buffer N] [--retry-on-failure] "	  "[--send-buffer N]\n"	  "\t[--server S] [--server-name S] [--session-cookies]\n"#ifdef HAVE_SSL	  "\t[--ssl] [--ssl-ciphers L] [--ssl-no-reuse]\n"#endif	  "\t[--think-timeout X] [--timeout X] [--uri S] [--verbose] "	  "[--version]\n"	  "\t[--wlog y|n,file] [--wsess N,N,X] [--wsesslog N,X,file]\n"	  "\t[--wset N,X]\n",	  prog_name);}voidpanic (const char *msg, ...){  va_list va;  va_start (va, msg);  vfprintf (stderr, msg, va);  va_end (va);  exit (1);}voidno_op (void){}static voidperf_sample (Timer *t, Any_Type regarg){  Any_Type callarg;  callarg.d = 1.0 / (timer_now () - perf_sample_start);  event_signal (EV_PERF_SAMPLE, 0, callarg);  /* prepare for next sample interval: */  perf_sample_start = timer_now ();  timer_schedule (perf_sample, regarg, RATE_INTERVAL);}intmain (int argc, char **argv){  extern Load_Generator uri_fixed, uri_wlog, uri_wset, conn_rate, call_seq;  extern Load_Generator wsess, wsesslog, wsesspage, sess_cookie, misc;  extern Stat_Collector stats_basic, session_stat;  extern Stat_Collector stats_print_reply;  extern char *optarg;  int session_workload = 0;  int num_gen = 3;  Load_Generator *gen[5] =    {      &call_seq,      &uri_fixed,      &conn_rate,    };  int num_stats = 1;  Stat_Collector *stat[3] =    {      &stats_basic    };  int i, ch, longindex;  u_int minor, major;  char *end, *name;  Any_Type arg;  void *flag;  Time t;#ifdef __FreeBSD__  /* This works around a bug in earlier versions of FreeBSD that cause     non-finite IEEE arithmetic to cause SIGFPE instead of the     non-finite arithmetic as defined by IEEE.  */  fpsetmask (0);#endif  object_type_size[OBJ_CONN] = sizeof (Conn);  object_type_size[OBJ_CALL] = sizeof (Call);  param.http_version = 0x10001;		/* default to HTTP/1.1 */  param.client.id = 0;  param.client.num_clients = 1;  param.server = "localhost";  param.port = -1;  param.uri = "/";  param.num_calls = 1;  param.burst_len = 1;  param.num_conns = 1;  /* These should be set to the minimum of 2*bandwidth*delay and the     maximum request/reply size for single-call connections.  */  param.send_buffer_size =  4096;  param.recv_buffer_size = 16384;  param.rate.dist = DETERMINISTIC;#ifdef HAVE_SSL  param.ssl_reuse = 1;#endif  /* get program name: */  prog_name = strrchr (argv[0], '/');  if (prog_name)    ++prog_name;  else    prog_name = argv[0];  /* process command line options: */  while ((ch = getopt_long (argc, argv, "d:hvV", longopts, &longindex)) >= 0)    {      switch (ch)	{	case 0:	  flag = longopts[longindex].flag;	  if (flag == &param.method)	    param.method = optarg;	  else if (flag == &param.additional_header)	    param.additional_header = optarg;	  else if (flag == &param.num_calls)	    {	      errno = 0;	      param.num_calls = strtoul (optarg, &end, 10);	      if (errno == ERANGE || end == optarg || *end)		{		  fprintf (stderr, "%s: illegal number of calls %s\n",			   prog_name, optarg);		  exit (1);		}	    }	  else if (flag == &param.http_version)	    {	      if (sscanf (optarg, "%u.%u", &major, &minor) != 2)		{		  fprintf (stderr, "%s: illegal version number %s\n",			   prog_name, optarg);		  exit (1);		}	      param.http_version = (major << 16) | (minor & 0xffff);	    }	  else if (flag == &param.burst_len)	    {	      errno = 0;	      param.burst_len = strtoul (optarg, &end, 10);	      if (errno == ERANGE || end == optarg || *end		  || param.burst_len < 1)		{		  fprintf (stderr, "%s: illegal burst-length %s\n",			   prog_name, optarg);		  exit (1);		}	    }	  else if (flag == &param.failure_status)	    {	      errno = 0;	      param.failure_status = strtoul (optarg, &end, 10);	      if (errno == ERANGE || end == optarg || *end		  || param.failure_status <= 0)		{		  fprintf (stderr, "%s: illegal failure status %s\n",			   prog_name, optarg);		  exit (1);		}	    }	  else if (flag == &param.num_conns)	    {	      errno = 0;	      param.num_conns = strtoul (optarg, &end, 10);	      if (errno == ERANGE || end == optarg || *end)		{		  fprintf (stderr, "%s: illegal number of connections %s\n",			   prog_name, optarg);		  exit (1);		}	    }	  else if (flag == &param.max_conns)	    {	      errno = 0;	      param.max_conns = strtoul (optarg, &end, 10);	      if (errno == ERANGE || end == optarg || *end		  || param.max_conns < 0)		{		  fprintf (stderr, "%s: illegal max. # of connection %s\n",			   prog_name, optarg);		  exit (1);		}	    }	  else if (flag == &param.max_piped)	    {	      errno = 0;	      param.max_piped = strtoul (optarg, &end, 10);	      if (errno == ERANGE || end == optarg || *end		  || param.max_piped < 0)		{		  fprintf (stderr, "%s: illegal max. # of piped calls %s\n",			   prog_name, optarg);		  exit (1);		}	    }	  else if (flag == &param.port)	    {	      errno = 0;	      param.port = strtoul (optarg, &end, 10);	      if (errno == ERANGE || end == optarg || *end		  || (unsigned) param.port > 0xffff)		{		  fprintf (stderr, "%s: illegal port number %s\n",			   prog_name, optarg);		  exit (1);		}	    }	  else if (flag == &param.print_request || flag == &param.print_reply)	    {	      int val;	      if (!optarg)		val = PRINT_HEADER | PRINT_BODY;	      else		switch (tolower (optarg[0]))		  {		  case 'h': val = PRINT_HEADER;	break;		  case 'b': val = PRINT_BODY;	break;		  default:  val = PRINT_HEADER | PRINT_BODY; break;		  }	      *(int *) flag = val;	    }	  else if (flag == &param.rate)	    {	      errno = 0;	      param.rate.rate_param = strtod (optarg, &end);	      if (errno == ERANGE || end == optarg || *end)		{		  fprintf (stderr, "%s: illegal request rate %s\n",			   prog_name, optarg);		  exit (1);		}	      if (param.rate.rate_param <= 0.0)		param.rate.mean_iat = 0.0;	      else		param.rate.mean_iat = 1/param.rate.rate_param;	      param.rate.dist = DETERMINISTIC;	    }	  else if (flag == &param.rate.mean_iat)	/* --period */	    {	      param.rate.dist = DETERMINISTIC;	      if (!isdigit (*optarg))		switch (tolower(*optarg++))		  {		  case 'd': param.rate.dist = DETERMINISTIC; break;		  case 'u': param.rate.dist = UNIFORM; break;		  case 'e': param.rate.dist = EXPONENTIAL; break;		  default:		    fprintf (stderr, "%s: illegal interarrival distribution "			     "'%c' in %s\n",			     prog_name, optarg[-1], optarg - 1);		    exit (1);		  }	      /* remaining params depend on selected distribution: */	      errno = 0;	      switch (param.rate.dist)		{		case DETERMINISTIC:		case EXPONENTIAL:		  param.rate.mean_iat = strtod (optarg, &end);		  if (errno == ERANGE || end == optarg || *end		      || param.rate.mean_iat < 0)		    {		      fprintf (stderr, "%s: illegal mean interarrival "			       "time %s\n", prog_name, optarg);		      exit (1);		    }		  break;		case UNIFORM:		  param.rate.min_iat = strtod (optarg, &end);		  if (errno == ERANGE || end == optarg		      || param.rate.min_iat < 0)		    {		      fprintf (stderr, "%s: illegal minimum interarrival "			       "time %s\n", prog_name, optarg);		      exit (1);		    }		  if (*end != ',')		    {		      fprintf (stderr, "%s: minimum interarrival time not "			       "followed by `,MAX_IAT' (rest: `%s')\n",			       prog_name, end);		      exit (1);		    }		  optarg = end + 1;		  param.rate.max_iat = strtod (optarg, &end);		  if (errno == ERANGE || end == optarg || *end		      || param.rate.max_iat < 0)		    {		      fprintf (stderr, "%s: illegal request period %s\n",			       prog_name, optarg);		      exit (1);		    }		  param.rate.mean_iat = 0.5*(param.rate.min_iat					     + param.rate.max_iat);		  break;		default:		  fprintf (stderr, "%s: internal error parsing %s\n",			   prog_name, optarg);		  exit (1);		  break;		}	      param.rate.rate_param = ((param.rate.mean_iat <= 0.0)				       ? 0.0 : (1.0 / param.rate.mean_iat));	    }	  else if (flag == &param.recv_buffer_size)	    {	      errno = 0;	      param.recv_buffer_size = strtoul (optarg, &end, 10);	      if (errno == ERANGE || end == optarg || *end		  || param.port > 0xffff)		{		  fprintf (stderr, "%s: illegal receive buffer size %s\n",			   prog_name, optarg);		  exit (1);		}	    }	  else if (flag == &param.send_buffer_size)	    {	      errno = 0;	      param.send_buffer_size = strtoul (optarg, &end, 10);	      if (errno == ERANGE || end == optarg || *end		  || param.port > 0xffff)		{		  fprintf (stderr, "%s: illegal send buffer size %s\n",			   prog_name, optarg);		  exit (1);		}	    }	  else if (flag == &param.client)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -