随想录(webbench压力测试代码)

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

               

 

【 声明:版权所有,欢迎转载,请勿用于商业用途。  联系信箱:feixiaoxing @163.com】

 

    关于压力测试,网上有很多的代码。但是,我个人还是觉得这份webbench代码写得比较好,大概也可能是因为我自己比较偏好小而精的代码吧。压力测试一般是指让server承受一定的负载,进而可以验证server的cpu使用率、io速度、mem和swap大小、响应速度、服务器程序稳定性、并发性能等等。

 

    原来webbench是由webbench.c和socket.c两个文件组成,这里为了阅读的方便,我自己将两份代码合在了一起,其实是一样的。

/* * (C) Radim Kolar 1997-2004 * This is free software, see GNU Public License version 2 for * details. * * Simple forking WWW Server benchmark: * * Usage: *   webbench --help * * Return codes: *    0 - sucess *    1 - benchmark failed (server is not on-line) *    2 - bad param *    3 - internal error, fork failed *  */ #include <sys/types.h>#include <sys/socket.h>#include <fcntl.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#include <sys/time.h>#include <string.h>#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <stdarg.h>int Socket(const char *host, int clientPort){    int sock;    unsigned long inaddr;    struct sockaddr_in ad;    struct hostent *hp;        memset(&ad, 0, sizeof(ad));    ad.sin_family = AF_INET;    inaddr = inet_addr(host);    if (inaddr != INADDR_NONE)        memcpy(&ad.sin_addr, &inaddr, sizeof(inaddr));    else    {        hp = gethostbyname(host);        if (hp == NULL)            return -1;        memcpy(&ad.sin_addr, hp->h_addr, hp->h_length);    }    ad.sin_port = htons(clientPort);        sock = socket(AF_INET, SOCK_STREAM, 0);    if (sock < 0)        return sock;    if (connect(sock, (struct sockaddr *)&ad, sizeof(ad)) < 0)        return -1;    return sock;}#include <unistd.h>#include <sys/param.h>#include <rpc/types.h>#include <getopt.h>#include <strings.h>#include <time.h>#include <signal.h>/* values */volatile int timerexpired=0;int speed=0;int failed=0;int bytes=0;/* globals */int http10=1; /* 0 - http/0.9, 1 - http/1.0, 2 - http/1.1 *//* Allow: GET, HEAD, OPTIONS, TRACE */#define METHOD_GET 0#define METHOD_HEAD 1#define METHOD_OPTIONS 2#define METHOD_TRACE 3#define PROGRAM_VERSION "1.5"int method=METHOD_GET;int clients=1;int force=0;int force_reload=0;int proxyport=80;char *proxyhost=NULL;int benchtime=30;/* internal */int mypipe[2];char host[MAXHOSTNAMELEN];#define REQUEST_SIZE 2048char request[REQUEST_SIZE];static const struct option long_options[]={ {"force",no_argument,&force,1}, {"reload",no_argument,&force_reload,1}, {"time",required_argument,NULL,'t'}, {"help",no_argument,NULL,'?'}, {"http09",no_argument,NULL,'9'}, {"http10",no_argument,NULL,'1'}, {"http11",no_argument,NULL,'2'}, {"get",no_argument,&method,METHOD_GET}, {"head",no_argument,&method,METHOD_HEAD}, {"options",no_argument,&method,METHOD_OPTIONS}, {"trace",no_argument,&method,METHOD_TRACE}, {"version",no_argument,NULL,'V'}, {"proxy",required_argument,NULL,'p'}, {"clients",required_argument,NULL,'c'}, {NULL,0,NULL,0}};/* prototypes */static void benchcore(const char* host,const int port, const char *request);static int bench(void);static void build_request(const char *url);static void alarm_handler(int signal){   timerexpired=1;} static void usage(void){   fprintf(stderr"webbench [option]... URL\n" "  -f|--force               Don't wait for reply from server.\n" "  -r|--reload              Send reload request - Pragma: no-cache.\n" "  -t|--time <sec>          Run benchmark for <sec> seconds. Default 30.\n" "  -p|--proxy <server:port> Use proxy server for request.\n" "  -c|--clients <n>         Run <n> HTTP clients at once. Default one.\n" "  -9|--http09              Use HTTP/0.9 style requests.\n" "  -1|--http10              Use HTTP/1.0 protocol.\n" "  -2|--http11              Use HTTP/1.1 protocol.\n" "  --get                    Use GET request method.\n" "  --head                   Use HEAD request method.\n" "  --options                Use OPTIONS request method.\n" "  --trace                  Use TRACE request method.\n" "  -?|-h|--help             This information.\n" "  -V|--version             Display program version.\n" );};int main(int argc, char *argv[])int opt=0int options_index=0char *tmp=NULLif(argc==1) {   usage();          return 2; }  while((opt=getopt_long(argc,argv,"912Vfrt:p:c:?h",long_options,&options_index))!=EOF ) {  switch(opt)  {   case  0 : break;   case 'f': force=1;break;   case 'r': force_reload=1;break;    case '9': http10=0;break;   case '1': http10=1;break;   case '2': http10=2;break;   case 'V': printf(PROGRAM_VERSION"\n");exit(0);   case 't': benchtime=atoi(optarg);break;         case 'p':       /* proxy server parsing server:port */      tmp=strrchr(optarg,':');      proxyhost=optarg;      if(tmp==NULL)      {       break;      }      if(tmp==optarg)      {       fprintf(stderr,"Error in option --proxy %s: Missing hostname.\n",optarg);       return 2;      }      if(tmp==optarg+strlen(optarg)-1)      {       fprintf(stderr,"Error in option --proxy %s Port number is missing.\n",optarg);       return 2;      }      *tmp='\0';      proxyport=atoi(tmp+1);break;   case ':':   case 'h':   case '?': usage();return 2;break;   case 'c': clients=atoi(optarg);break;  } }  if(optind==argc) {                      fprintf(stderr,"webbench: Missing URL!\n");        usage();        return 2;                    } if(clients==0) clients=1if(benchtime==0) benchtime=60/* Copyright */ fprintf(stderr,"Webbench - Simple Web Benchmark "PROGRAM_VERSION"\n"  "Copyright (c) Radim Kolar 1997-2004, GPL Open Source Software.\n"  ); build_request(argv[optind]); /* print bench info */ printf("\nBenchmarking: "); switch(method) {  case METHOD_GET:  default:   printf("GET");breakcase METHOD_OPTIONS:   printf("OPTIONS");breakcase METHOD_HEAD:   printf("HEAD");breakcase METHOD_TRACE:   printf("TRACE");break; } printf(" %s",argv[optind]); switch(http10) {  case 0: printf(" (using HTTP/0.9)");breakcase 2: printf(" (using HTTP/1.1)");break; } printf("\n"); if(clients==1) printf("1 client"); else   printf("%d clients",clients); printf(", running %d sec", benchtime); if(force) printf(", early socket close"); if(proxyhost!=NULL) printf(", via proxy server %s:%d",proxyhost,proxyport); if(force_reload) printf(", forcing reload"); printf(".\n"); return bench();}void build_request(const char *url)char tmp[10];  int i;  bzero(host,MAXHOSTNAMELEN);  bzero(request,REQUEST_SIZE);  if(force_reload && proxyhost!=NULL && http10<1) http10=1if(method==METHOD_HEAD && http10<1) http10=1if(method==METHOD_OPTIONS && http10<2) http10=2if(method==METHOD_TRACE && http10<2) http10=2switch(method)  {   default:   case METHOD_GET: strcpy(request,"GET");break;   case METHOD_HEAD: strcpy(request,"HEAD");break;   case METHOD_OPTIONS: strcpy(request,"OPTIONS");break;   case METHOD_TRACE: strcpy(request,"TRACE");break;  }      strcat(request," ");  if(NULL==strstr(url,"://"))  {   fprintf(stderr, "\n%s: is not a valid URL.\n",url);   exit(2);  }  if(strlen(url)>1500)  {         fprintf(stderr,"URL is too long.\n");  exit(2);  }  if(proxyhost==NULL)    if (0!=strncasecmp("http://",url,7))     { fprintf(stderr,"\nOnly HTTP protocol is directly supported, set --proxy for others.\n");             exit(2);           }  /* protocol/host delimiter */  i=strstr(url,"://")-url+3/* printf("%d\n",i); */  if(strchr(url+i,'/')==NULL) {                                fprintf(stderr,"\nInvalid URL syntax - hostname don't ends with '/'.\n");                                exit(2);                              }  if(proxyhost==NULL)  {   /* get port from hostname */   if(index(url+i,':')!=NULL &&      index(url+i,':')<index(url+i,'/'))   {    strncpy(host,url+i,strchr(url+i,':')-url-i);    bzero(tmp,10);    strncpy(tmp,index(url+i,':')+1,strchr(url+i,'/')-index(url+i,':')-1);    /* printf("tmp=%s\n",tmp); */    proxyport=atoi(tmp);    if(proxyport==0) proxyport=80;   } else   {     strncpy(host,url+i,strcspn(url+i,"/"));   }   // printf("Host=%s\n",host);   strcat(request+strlen(request),url+i+strcspn(url+i,"/"));  } else  {   // printf("ProxyHost=%s\nProxyPort=%d\n",proxyhost,proxyport);   strcat(request,url);  }  if(http10==1)   strcat(request," HTTP/1.0");  else if (http10==2)   strcat(request," HTTP/1.1");  strcat(request,"\r\n");  if(http10>0)   strcat(request,"User-Agent: WebBench "PROGRAM_VERSION"\r\n");  if(proxyhost==NULL && http10>0)  {   strcat(request,"Host: ");   strcat(request,host);   strcat(request,"\r\n");  }  if(force_reload && proxyhost!=NULL)  {   strcat(request,"Pragma: no-cache\r\n");  }  if(http10>1)   strcat(request,"Connection: close\r\n");  /* add empty line at end */  if(http10>0) strcat(request,"\r\n");   // printf("Req=%s\n",request);}/* vraci system rc error kod */static int bench(void)int i,j,k;   pid_t pid=0;  FILE *f;  /* check avaibility of target server */  i=Socket(proxyhost==NULL?host:proxyhost,proxyport);  if(i<0) {     fprintf(stderr,"\nConnect to server failed. Aborting benchmark.\n");           return 1;         }  close(i);  /* create pipe */  if(pipe(mypipe))  {   perror("pipe failed.");   return 3;  }  /* not needed, since we have alarm() in childrens */  /* wait 4 next system clock tick */  /*  cas=time(NULL);  while(time(NULL)==cas)        sched_yield();  */  /* fork childs */  for(i=0;i<clients;i++)  {    pid=fork();    if(pid <= (pid_t) 0)    {     /* child process or error*/            sleep(1); /* make childs faster */     break;    }  }  if( pid< (pid_t) 0)  {          fprintf(stderr,"problems forking worker no. %d\n",i);   perror("fork failed.");   return 3;  }  if(pid== (pid_t) 0)  {    /* I am a child */    if(proxyhost==NULL)      benchcore(host,proxyport,request);         else      benchcore(proxyhost,proxyport,request);         /* write results to pipe */  f=fdopen(mypipe[1],"w");  if(f==NULL)  {   perror("open pipe for writing failed.");   return 3;  }  /* fprintf(stderr,"Child - %d %d\n",speed,failed); */  fprintf(f,"%d %d %d\n",speed,failed,bytes);  fclose(f);  return 0;  } else  {   f=fdopen(mypipe[0],"r");   if(f==NULL)    {    perror("open pipe for reading failed.");    return 3;   }   setvbuf(f,NULL,_IONBF,0);   speed=0;          failed=0;          bytes=0;   while(1)   {    pid=fscanf(f,"%d %d %d",&i,&j,&k);    if(pid<2)                  {                       fprintf(stderr,"Some of our childrens died.\n");                       break;                  }    speed+=i;    failed+=j;    bytes+=k;    /* fprintf(stderr,"*Knock* %d %d read=%d\n",speed,failed,pid); */    if(--clients==0) break;   }   fclose(f);  printf("\nSpeed=%d pages/min, %d bytes/sec.\nRequests: %d susceed, %d failed.\n",    (int)((speed+failed)/(benchtime/60.0f)),    (int)(bytes/(float)benchtime),    speed,    failed);  }  return i;}void benchcore(const char *host,const int port,const char *req)int rlen; char buf[1500]; int s,i; struct sigaction sa; /* setup alarm signal handler */ sa.sa_handler=alarm_handler; sa.sa_flags=0if(sigaction(SIGALRM,&sa,NULL))    exit(3); alarm(benchtime); rlen=strlen(req); nexttry:while(1) {    if(timerexpired)    {       if(failed>0)       {          /* fprintf(stderr,"Correcting failed by signal\n"); */          failed--;       }       return;    }    s=Socket(host,port);                              if(s<0) { failed++;continue;}     if(rlen!=write(s,req,rlen)) {failed++;close(s);continue;}    if(http10==0)      if(shutdown(s,1)) { failed++;close(s);continue;}    if(force==0)     {            /* read all available data from socket */     while(1)     {              if(timerexpired) break;        i=read(s,buf,1500);              /* fprintf(stderr,"%d\n",i); */       if(i<0)               {                  failed++;                 close(s);                 goto nexttry;              }        else         if(i==0) break;         else          bytes+=i;     }    }    if(close(s)) {failed++;continue;}    speed++; }}

 

补充:

    redis的benchmark也不错,特意粘贴在下面。

/* Redis benchmark utility. * * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * *   * Redistributions of source code must retain the above copyright notice, *     this list of conditions and the following disclaimer. *   * Redistributions in binary form must reproduce the above copyright *     notice, this list of conditions and the following disclaimer in the *     documentation and/or other materials provided with the distribution. *   * Neither the name of Redis nor the names of its contributors may be used *     to endorse or promote products derived from this software without *     specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */#include "fmacros.h"#include <stdio.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include <errno.h>#include <time.h>#include <sys/time.h>#include <signal.h>#include <assert.h>#include "ae.h"#include "hiredis.h"#include "sds.h"#include "adlist.h"#include "zmalloc.h"#define REDIS_NOTUSED(V) ((void) V)#define RANDPTR_INITIAL_SIZE 8static struct config {    aeEventLoop *el;    const char *hostip;    int hostport;    const char *hostsocket;    int numclients;    int liveclients;    int requests;    int requests_issued;    int requests_finished;    int keysize;    int datasize;    int randomkeys;    int randomkeys_keyspacelen;    int keepalive;    int pipeline;    long long start;    long long totlatency;    long long *latency;    const char *title;    list *clients;    int quiet;    int csv;    int loop;    int idlemode;    int dbnum;    sds dbnumstr;    char *tests;    char *auth;} config;typedef struct _client {    redisContext *context;    sds obuf;    char **randptr;         /* Pointers to :rand: strings inside the command buf */    size_t randlen;         /* Number of pointers in client->randptr */    size_t randfree;        /* Number of unused pointers in client->randptr */    unsigned int written;   /* Bytes of 'obuf' already written */    long long start;        /* Start time of a request */    long long latency;      /* Request latency */    int pending;            /* Number of pending requests (replies to consume) */    int selectlen;  /* If non-zero, a SELECT of 'selectlen' bytes is currently                       used as a prefix of the pipline of commands. This gets                       discarded the first time it's sent. */} *client;/* Prototypes */static void writeHandler(aeEventLoop *el, int fd, void *privdata, int mask);static void createMissingClients(client c);/* Implementation */static long long ustime(void) {    struct timeval tv;    long long ust;    gettimeofday(&tv, NULL);    ust = ((long)tv.tv_sec)*1000000;    ust += tv.tv_usec;    return ust;}static long long mstime(void) {    struct timeval tv;    long long mst;    gettimeofday(&tv, NULL);    mst = ((long long)tv.tv_sec)*1000;    mst += tv.tv_usec/1000;    return mst;}static void freeClient(client c) {    listNode *ln;    aeDeleteFileEvent(config.el,c->context->fd,AE_WRITABLE);    aeDeleteFileEvent(config.el,c->context->fd,AE_READABLE);    redisFree(c->context);    sdsfree(c->obuf);    zfree(c->randptr);    zfree(c);    config.liveclients--;    ln = listSearchKey(config.clients,c);    assert(ln != NULL);    listDelNode(config.clients,ln);}static void freeAllClients(void) {    listNode *ln = config.clients->head, *next;    while(ln) {        next = ln->next;        freeClient(ln->value);        ln = next;    }}static void resetClient(client c) {    aeDeleteFileEvent(config.el,c->context->fd,AE_WRITABLE);    aeDeleteFileEvent(config.el,c->context->fd,AE_READABLE);    aeCreateFileEvent(config.el,c->context->fd,AE_WRITABLE,writeHandler,c);    c->written = 0;    c->pending = config.pipeline;}static void randomizeClientKey(client c) {    size_t i;    for (i = 0; i < c->randlen; i++) {        char *p = c->randptr[i]+11;        size_t r = random() % config.randomkeys_keyspacelen;        size_t j;        for (j = 0; j < 12; j++) {            *p = '0'+r%10;            r/=10;            p--;        }    }}static void clientDone(client c) {    if (config.requests_finished == config.requests) {        freeClient(c);        aeStop(config.el);        return;    }    if (config.keepalive) {        resetClient(c);    } else {        config.liveclients--;        createMissingClients(c);        config.liveclients++;        freeClient(c);    }}static void readHandler(aeEventLoop *el, int fd, void *privdata, int mask) {    client c = privdata;    void *reply = NULL;    REDIS_NOTUSED(el);    REDIS_NOTUSED(fd);    REDIS_NOTUSED(mask);    /* Calculate latency only for the first read event. This means that the     * server already sent the reply and we need to parse it. Parsing overhead     * is not part of the latency, so calculate it only once, here. */    if (c->latency < 0) c->latency = ustime()-(c->start);    if (redisBufferRead(c->context) != REDIS_OK) {        fprintf(stderr,"Error: %s\n",c->context->errstr);        exit(1);    } else {        while(c->pending) {            if (redisGetReply(c->context,&reply) != REDIS_OK) {                fprintf(stderr,"Error: %s\n",c->context->errstr);                exit(1);            }            if (reply != NULL) {                if (reply == (void*)REDIS_REPLY_ERROR) {                    fprintf(stderr,"Unexpected error reply, exiting...\n");                    exit(1);                }                freeReplyObject(reply);                if (c->selectlen) {                    size_t j;                    /* This is the OK from SELECT. Just discard the SELECT                     * from the buffer. */                    c->pending--;                    sdsrange(c->obuf,c->selectlen,-1);                    /* We also need to fix the pointers to the strings                     * we need to randomize. */                    for (j = 0; j < c->randlen; j++)                        c->randptr[j] -= c->selectlen;                    c->selectlen = 0;                    continue;                }                if (config.requests_finished < config.requests)                    config.latency[config.requests_finished++] = c->latency;                c->pending--;                if (c->pending == 0) {                    clientDone(c);                    break;                }            } else {                break;            }        }    }}static void writeHandler(aeEventLoop *el, int fd, void *privdata, int mask) {    client c = privdata;    REDIS_NOTUSED(el);    REDIS_NOTUSED(fd);    REDIS_NOTUSED(mask);    /* Initialize request when nothing was written. */    if (c->written == 0) {        /* Enforce upper bound to number of requests. */        if (config.requests_issued++ >= config.requests) {            freeClient(c);            return;        }        /* Really initialize: randomize keys and set start time. */        if (config.randomkeys) randomizeClientKey(c);        c->start = ustime();        c->latency = -1;    }    if (sdslen(c->obuf) > c->written) {        void *ptr = c->obuf+c->written;        int nwritten = write(c->context->fd,ptr,sdslen(c->obuf)-c->written);        if (nwritten == -1) {            if (errno != EPIPE)                fprintf(stderr, "Writing to socket: %s\n", strerror(errno));            freeClient(c);            return;        }        c->written += nwritten;        if (sdslen(c->obuf) == c->written) {            aeDeleteFileEvent(config.el,c->context->fd,AE_WRITABLE);            aeCreateFileEvent(config.el,c->context->fd,AE_READABLE,readHandler,c);        }    }}/* Create a benchmark client, configured to send the command passed as 'cmd' of * 'len' bytes. * * The command is copied N times in the client output buffer (that is reused * again and again to send the request to the server) accordingly to the configured * pipeline size. * * Also an initial SELECT command is prepended in order to make sure the right * database is selected, if needed. The initial SELECT will be discarded as soon * as the first reply is received. * * To create a client from scratch, the 'from' pointer is set to NULL. If instead * we want to create a client using another client as reference, the 'from' pointer * points to the client to use as reference. In such a case the following * information is take from the 'from' client: * * 1) The command line to use. * 2) The offsets of the __rand_int__ elements inside the command line, used *    for arguments randomization. * * Even when cloning another client, the SELECT command is automatically prefixed * if needed. */static client createClient(char *cmd, size_t len, client from) {    int j;    client c = zmalloc(sizeof(struct _client));    if (config.hostsocket == NULL) {        c->context = redisConnectNonBlock(config.hostip,config.hostport);    } else {        c->context = redisConnectUnixNonBlock(config.hostsocket);    }    if (c->context->err) {        fprintf(stderr,"Could not connect to Redis at ");        if (config.hostsocket == NULL)            fprintf(stderr,"%s:%d: %s\n",config.hostip,config.hostport,c->context->errstr);        else            fprintf(stderr,"%s: %s\n",config.hostsocket,c->context->errstr);        exit(1);    }    /* Suppress hiredis cleanup of unused buffers for max speed. */    c->context->reader->maxbuf = 0;    /* Build the request buffer:     * Queue N requests accordingly to the pipeline size, or simply clone     * the example client buffer. */    c->obuf = sdsempty();    if (config.auth) {        char *buf = NULL;        int len = redisFormatCommand(&buf, "AUTH %s", config.auth);        c->obuf = sdscatlen(c->obuf, buf, len);        free(buf);    }    /* If a DB number different than zero is selected, prefix our request     * buffer with the SELECT command, that will be discarded the first     * time the replies are received, so if the client is reused the     * SELECT command will not be used again. */    if (config.dbnum != 0) {        c->obuf = sdscatprintf(c->obuf,"*2\r\n$6\r\nSELECT\r\n$%d\r\n%s\r\n",            (int)sdslen(config.dbnumstr),config.dbnumstr);        c->selectlen = sdslen(c->obuf);    } else {        c->selectlen = 0;    }    /* Append the request itself. */    if (from) {        c->obuf = sdscatlen(c->obuf,            from->obuf+from->selectlen,            sdslen(from->obuf)-from->selectlen);    } else {        for (j = 0; j < config.pipeline; j++)            c->obuf = sdscatlen(c->obuf,cmd,len);    }    c->written = 0;    c->pending = config.pipeline;    c->randptr = NULL;    c->randlen = 0;    if (c->selectlen) c->pending++;    /* Find substrings in the output buffer that need to be randomized. */    if (config.randomkeys) {        if (from) {            c->randlen = from->randlen;            c->randfree = 0;            c->randptr = zmalloc(sizeof(char*)*c->randlen);            /* copy the offsets. */            for (j = 0; j < (int)c->randlen; j++) {                c->randptr[j] = c->obuf + (from->randptr[j]-from->obuf);                /* Adjust for the different select prefix length. */                c->randptr[j] += c->selectlen - from->selectlen;            }        } else {            char *p = c->obuf;            c->randlen = 0;            c->randfree = RANDPTR_INITIAL_SIZE;            c->randptr = zmalloc(sizeof(char*)*c->randfree);            while ((p = strstr(p,"__rand_int__")) != NULL) {                if (c->randfree == 0) {                    c->randptr = zrealloc(c->randptr,sizeof(char*)*c->randlen*2);                    c->randfree += c->randlen;                }                c->randptr[c->randlen++] = p;                c->randfree--;                p += 12; /* 12 is strlen("__rand_int__). */            }        }    }    aeCreateFileEvent(config.el,c->context->fd,AE_WRITABLE,writeHandler,c);    listAddNodeTail(config.clients,c);    config.liveclients++;    return c;}static void createMissingClients(client c) {    int n = 0;    while(config.liveclients < config.numclients) {        createClient(NULL,0,c);        /* Listen backlog is quite limited on most systems */        if (++n > 64) {            usleep(50000);            n = 0;        }    }}static int compareLatency(const void *a, const void *b) {    return (*(long long*)a)-(*(long long*)b);}static void showLatencyReport(void) {    int i, curlat = 0;    float perc, reqpersec;    reqpersec = (float)config.requests_finished/((float)config.totlatency/1000);    if (!config.quiet && !config.csv) {        printf("====== %s ======\n", config.title);        printf("  %d requests completed in %.2f seconds\n", config.requests_finished,            (float)config.totlatency/1000);        printf("  %d parallel clients\n", config.numclients);        printf("  %d bytes payload\n", config.datasize);        printf("  keep alive: %d\n", config.keepalive);        printf("\n");        qsort(config.latency,config.requests,sizeof(long long),compareLatency);        for (i = 0; i < config.requests; i++) {            if (config.latency[i]/1000 != curlat || i == (config.requests-1)) {                curlat = config.latency[i]/1000;                perc = ((float)(i+1)*100)/config.requests;                printf("%.2f%% <= %d milliseconds\n", perc, curlat);            }        }        printf("%.2f requests per second\n\n", reqpersec);    } else if (config.csv) {        printf("\"%s\",\"%.2f\"\n", config.title, reqpersec);    } else {        printf("%s: %.2f requests per second\n", config.title, reqpersec);    }}static void benchmark(char *title, char *cmd, int len) {    client c;    config.title = title;    config.requests_issued = 0;    config.requests_finished = 0;    c = createClient(cmd,len,NULL);    createMissingClients(c);    config.start = mstime();    aeMain(config.el);    config.totlatency = mstime()-config.start;    showLatencyReport();    freeAllClients();}/* Returns number of consumed options. */int parseOptions(int argc, const char **argv) {    int i;    int lastarg;    int exit_status = 1;    for (i = 1; i < argc; i++) {        lastarg = (i == (argc-1));        if (!strcmp(argv[i],"-c")) {            if (lastarg) goto invalid;            config.numclients = atoi(argv[++i]);        } else if (!strcmp(argv[i],"-n")) {            if (lastarg) goto invalid;            config.requests = atoi(argv[++i]);        } else if (!strcmp(argv[i],"-k")) {            if (lastarg) goto invalid;            config.keepalive = atoi(argv[++i]);        } else if (!strcmp(argv[i],"-h")) {            if (lastarg) goto invalid;            config.hostip = strdup(argv[++i]);        } else if (!strcmp(argv[i],"-p")) {            if (lastarg) goto invalid;            config.hostport = atoi(argv[++i]);        } else if (!strcmp(argv[i],"-s")) {            if (lastarg) goto invalid;            config.hostsocket = strdup(argv[++i]);        } else if (!strcmp(argv[i],"-a") ) {            if (lastarg) goto invalid;            config.auth = strdup(argv[++i]);        } else if (!strcmp(argv[i],"-d")) {            if (lastarg) goto invalid;            config.datasize = atoi(argv[++i]);            if (config.datasize < 1) config.datasize=1;            if (config.datasize > 1024*1024*1024) config.datasize = 1024*1024*1024;        } else if (!strcmp(argv[i],"-P")) {            if (lastarg) goto invalid;            config.pipeline = atoi(argv[++i]);            if (config.pipeline <= 0) config.pipeline=1;        } else if (!strcmp(argv[i],"-r")) {            if (lastarg) goto invalid;            config.randomkeys = 1;            config.randomkeys_keyspacelen = atoi(argv[++i]);            if (config.randomkeys_keyspacelen < 0)                config.randomkeys_keyspacelen = 0;        } else if (!strcmp(argv[i],"-q")) {            config.quiet = 1;        } else if (!strcmp(argv[i],"--csv")) {            config.csv = 1;        } else if (!strcmp(argv[i],"-l")) {            config.loop = 1;        } else if (!strcmp(argv[i],"-I")) {            config.idlemode = 1;        } else if (!strcmp(argv[i],"-t")) {            if (lastarg) goto invalid;            /* We get the list of tests to run as a string in the form             * get,set,lrange,...,test_N. Then we add a comma before and             * after the string in order to make sure that searching             * for ",testname," will always get a match if the test is             * enabled. */            config.tests = sdsnew(",");            config.tests = sdscat(config.tests,(char*)argv[++i]);            config.tests = sdscat(config.tests,",");            sdstolower(config.tests);        } else if (!strcmp(argv[i],"--dbnum")) {            if (lastarg) goto invalid;            config.dbnum = atoi(argv[++i]);            config.dbnumstr = sdsfromlonglong(config.dbnum);        } else if (!strcmp(argv[i],"--help")) {            exit_status = 0;            goto usage;        } else {            /* Assume the user meant to provide an option when the arg starts             * with a dash. We're done otherwise and should use the remainder             * as the command and arguments for running the benchmark. */            if (argv[i][0] == '-') goto invalid;            return i;        }    }    return i;invalid:    printf("Invalid option \"%s\" or option argument missing\n\n",argv[i]);usage:    printf("Usage: redis-benchmark [-h <host>] [-p <port>] [-c <clients>] [-n <requests]> [-k <boolean>]\n\n"" -h <hostname>      Server hostname (default 127.0.0.1)\n"" -p <port>          Server port (default 6379)\n"" -s <socket>        Server socket (overrides host and port)\n"" -a <password>      Password for Redis Auth\n"" -c <clients>       Number of parallel connections (default 50)\n"" -n <requests>      Total number of requests (default 10000)\n"" -d <size>          Data size of SET/GET value in bytes (default 2)\n"" -dbnum <db>        SELECT the specified db number (default 0)\n"" -k <boolean>       1=keep alive 0=reconnect (default 1)\n"" -r <keyspacelen>   Use random keys for SET/GET/INCR, random values for SADD\n""  Using this option the benchmark will expand the string __rand_int__\n""  inside an argument with a 12 digits number in the specified range\n""  from 0 to keyspacelen-1. The substitution changes every time a command\n""  is executed. Default tests use this to hit random keys in the\n""  specified range.\n"" -P <numreq>        Pipeline <numreq> requests. Default 1 (no pipeline).\n"" -q                 Quiet. Just show query/sec values\n"" --csv              Output in CSV format\n"" -l                 Loop. Run the tests forever\n"" -t <tests>         Only run the comma separated list of tests. The test\n""                    names are the same as the ones produced as output.\n"" -I                 Idle mode. Just open N idle connections and wait.\n\n""Examples:\n\n"" Run the benchmark with the default configuration against 127.0.0.1:6379:\n""   $ redis-benchmark\n\n"" Use 20 parallel clients, for a total of 100k requests, against 192.168.1.1:\n""   $ redis-benchmark -h 192.168.1.1 -p 6379 -n 100000 -c 20\n\n"" Fill 127.0.0.1:6379 with about 1 million keys only using the SET test:\n""   $ redis-benchmark -t set -n 1000000 -r 100000000\n\n"" Benchmark 127.0.0.1:6379 for a few commands producing CSV output:\n""   $ redis-benchmark -t ping,set,get -n 100000 --csv\n\n"" Benchmark a specific command line:\n""   $ redis-benchmark -r 10000 -n 10000 eval 'return redis.call(\"ping\")' 0\n\n"" Fill a list with 10000 random elements:\n""   $ redis-benchmark -r 10000 -n 10000 lpush mylist __rand_int__\n\n"" On user specified command lines __rand_int__ is replaced with a random integer\n"" with a range of values selected by the -r option.\n"    );    exit(exit_status);}int showThroughput(struct aeEventLoop *eventLoop, long long id, void *clientData) {    REDIS_NOTUSED(eventLoop);    REDIS_NOTUSED(id);    REDIS_NOTUSED(clientData);    if (config.liveclients == 0) {        fprintf(stderr,"All clients disconnected... aborting.\n");        exit(1);    }    if (config.csv) return 250;    float dt = (float)(mstime()-config.start)/1000.0;    float rps = (float)config.requests_finished/dt;    printf("%s: %.2f\r", config.title, rps);    fflush(stdout);    return 250; /* every 250ms */}/* Return true if the named test was selected using the -t command line * switch, or if all the tests are selected (no -t passed by user). */int test_is_selected(char *name) {    char buf[256];    int l = strlen(name);    if (config.tests == NULL) return 1;    buf[0] = ',';    memcpy(buf+1,name,l);    buf[l+1] = ',';    buf[l+2] = '\0';    return strstr(config.tests,buf) != NULL;}int main(int argc, const char **argv) {    int i;    char *data, *cmd;    int len;    client c;    srandom(time(NULL));    signal(SIGHUP, SIG_IGN);    signal(SIGPIPE, SIG_IGN);    config.numclients = 50;    config.requests = 10000;    config.liveclients = 0;    config.el = aeCreateEventLoop(1024*10);    aeCreateTimeEvent(config.el,1,showThroughput,NULL,NULL);    config.keepalive = 1;    config.datasize = 3;    config.pipeline = 1;    config.randomkeys = 0;    config.randomkeys_keyspacelen = 0;    config.quiet = 0;    config.csv = 0;    config.loop = 0;    config.idlemode = 0;    config.latency = NULL;    config.clients = listCreate();    config.hostip = "127.0.0.1";    config.hostport = 6379;    config.hostsocket = NULL;    config.tests = NULL;    config.dbnum = 0;    config.auth = NULL;    i = parseOptions(argc,argv);    argc -= i;    argv += i;    config.latency = zmalloc(sizeof(long long)*config.requests);    if (config.keepalive == 0) {        printf("WARNING: keepalive disabled, you probably need 'echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse' for Linux and 'sudo sysctl -w net.inet.tcp.msl=1000' for Mac OS X in order to use a lot of clients/requests\n");    }    if (config.idlemode) {        printf("Creating %d idle connections and waiting forever (Ctrl+C when done)\n", config.numclients);        c = createClient("",0,NULL); /* will never receive a reply */        createMissingClients(c);        aeMain(config.el);        /* and will wait for every */    }    /* Run benchmark with command in the remainder of the arguments. */    if (argc) {        sds title = sdsnew(argv[0]);        for (i = 1; i < argc; i++) {            title = sdscatlen(title, " ", 1);            title = sdscatlen(title, (char*)argv[i], strlen(argv[i]));        }        do {            len = redisFormatCommandArgv(&cmd,argc,argv,NULL);            benchmark(title,cmd,len);            free(cmd);        } while(config.loop);        return 0;    }    /* Run default benchmark suite. */    do {        data = zmalloc(config.datasize+1);        memset(data,'x',config.datasize);        data[config.datasize] = '\0';        if (test_is_selected("ping_inline") || test_is_selected("ping"))            benchmark("PING_INLINE","PING\r\n",6);        if (test_is_selected("ping_mbulk") || test_is_selected("ping")) {            len = redisFormatCommand(&cmd,"PING");            benchmark("PING_BULK",cmd,len);            free(cmd);        }        if (test_is_selected("set")) {            len = redisFormatCommand(&cmd,"SET key:__rand_int__ %s",data);            benchmark("SET",cmd,len);            free(cmd);        }        if (test_is_selected("get")) {            len = redisFormatCommand(&cmd,"GET key:__rand_int__");            benchmark("GET",cmd,len);            free(cmd);        }        if (test_is_selected("incr")) {            len = redisFormatCommand(&cmd,"INCR counter:__rand_int__");            benchmark("INCR",cmd,len);            free(cmd);        }        if (test_is_selected("lpush")) {            len = redisFormatCommand(&cmd,"LPUSH mylist %s",data);            benchmark("LPUSH",cmd,len);            free(cmd);        }        if (test_is_selected("lpop")) {            len = redisFormatCommand(&cmd,"LPOP mylist");            benchmark("LPOP",cmd,len);            free(cmd);        }        if (test_is_selected("sadd")) {            len = redisFormatCommand(&cmd,                "SADD myset element:__rand_int__");            benchmark("SADD",cmd,len);            free(cmd);        }        if (test_is_selected("spop")) {            len = redisFormatCommand(&cmd,"SPOP myset");            benchmark("SPOP",cmd,len);            free(cmd);        }        if (test_is_selected("lrange") ||            test_is_selected("lrange_100") ||            test_is_selected("lrange_300") ||            test_is_selected("lrange_500") ||            test_is_selected("lrange_600"))        {            len = redisFormatCommand(&cmd,"LPUSH mylist %s",data);            benchmark("LPUSH (needed to benchmark LRANGE)",cmd,len);            free(cmd);        }        if (test_is_selected("lrange") || test_is_selected("lrange_100")) {            len = redisFormatCommand(&cmd,"LRANGE mylist 0 99");            benchmark("LRANGE_100 (first 100 elements)",cmd,len);            free(cmd);        }        if (test_is_selected("lrange") || test_is_selected("lrange_300")) {            len = redisFormatCommand(&cmd,"LRANGE mylist 0 299");            benchmark("LRANGE_300 (first 300 elements)",cmd,len);            free(cmd);        }        if (test_is_selected("lrange") || test_is_selected("lrange_500")) {            len = redisFormatCommand(&cmd,"LRANGE mylist 0 449");            benchmark("LRANGE_500 (first 450 elements)",cmd,len);            free(cmd);        }        if (test_is_selected("lrange") || test_is_selected("lrange_600")) {            len = redisFormatCommand(&cmd,"LRANGE mylist 0 599");            benchmark("LRANGE_600 (first 600 elements)",cmd,len);            free(cmd);        }        if (test_is_selected("mset")) {            const char *argv[21];            argv[0] = "MSET";            for (i = 1; i < 21; i += 2) {                argv[i] = "key:__rand_int__";                argv[i+1] = data;            }            len = redisFormatCommandArgv(&cmd,21,argv,NULL);            benchmark("MSET (10 keys)",cmd,len);            free(cmd);        }        if (!config.csv) printf("\n");    } while(config.loop);    return 0;}



 

           

给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow
这里写图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值