[源码分析] 性能压测工具-webbench

用Python编写一个网站监测器 网站监测器通常用于监测网站的可用性和性能。它可以帮助网站管理员及时发现网站故障,保证网站的正常运行,同时也可以提高网站的访问速度和用户体验。在本篇博客中,我们将介绍如何使用Python编写一个简单的网站监测器,以检测网站是否可访问,并在发现故障时发送电子邮件通知。 阅读详情

[源码分析] 性能压测工具-webbench

second60  20180609

1. webbench简介

今天和大家介绍一个网站压测性能测试工具,名字叫webbench。

 

a) 可测试相同硬件,不同服务的性能及不同硬件上同一个服务的运行状况。

b) 可以向我们展示服务器:每秒钟相应的请求数和每秒钟传输数据量。

c) 可以模拟3万个并发连接去测试网站的负载能力。

 

同时,webbench的代码非常精简,源代码只有六百多行代码,C语言编写。适合学习和分析。学习后,可修改成其他的性能测试工具。

 

下载网址:http://home.tiscali.cz/~cz210552/webbench.html

 

2. webbench使用介绍

安装好webbench后,可以查看说明: ./webbench -h

[root@VM_0_9_centos webbench-1.5]# ./webbench
webbench [option]... URL
  -f|--force               Don't wait for reply from server.
  -r|--reload              Send reload request - Pragma: no-cache.
  -t|--time <sec>          Run benchmark for <sec> seconds. Default 30.
  -p|--proxy <server:port> Use proxy server for request.
  -c|--clients <n>         Run <n> HTTP clients at once. Default one.
  -9|--http09              Use HTTP/0.9 style requests.
  -1|--http10              Use HTTP/1.0 protocol.
  -2|--http11              Use HTTP/1.1 protocol.
  --get                    Use GET request method.
  --head                   Use HEAD request method.
  --options                Use OPTIONS request method.
  --trace                  Use TRACE request method.
  -?|-h|--help             This information.
  -V|--version             Display program version.

参数介绍:

-f  :不等待服务器数据返回

-r  :发送重新加载请求

-t <sec> : 运行总时长,默认30秒

-p <sever:port> : 设计代码服务器

-c <clients> : 设置运行多少个客户端进程

-9/-1/-2: HTTP协议版本

--get : get请求

--head: head 请求

--options: options 请求

--trace: trace请求

-?|-h|--help: 帮助信息

-V|--version: 版本信息

 

例子:

1. 定时十秒,开启一百个客户端进程请求www.baidu.com

./webbench  -t 10 -c 100 http://www.baidu.com/


3. webbench 流程介绍

1. 解析命令行参数,并初始化变量。

2. 构造HTTP请求

3. 选测试一个连接是否正常

4. 创建管道:主管理用来读,子管理用来写数据

5. 根据客户端数创建子进程

6. 每个子进程单独测试,并在定时器到了后,往管道写入自已测试数据

7. 主程进收到子进程数据后进行统计

8. 最后,主进程收到所有子进程数据后,结束并打印统计数据


4. webbench源码分析

socket.c 文件

#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>
// socket创建连接函数
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;
}

webbench.c 文件

#include "socket.c"
#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 */
// http版本
int http10=1; /* 0 - http/0.9, 1 - http/1.0, 2 - http/1.1 */

/* Allow: GET, HEAD, OPTIONS, TRACE */
// http请求方法
#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 2048
char 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=0;
 int options_index=0;
 char *tmp=NULL;
 if(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=1;
 if(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");break;
 case METHOD_OPTIONS:
     printf("OPTIONS");break;
 case METHOD_HEAD:
     printf("HEAD");break;
 case METHOD_TRACE:
     printf("TRACE");break;
 }
 printf(" %s",argv[optind]);
 switch(http10)
 {
 case 0: printf(" (using HTTP/0.9)");break;
 case 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();
}

// 2.构造HTTP请求
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=1;
  if(method==METHOD_HEAD && http10<1) http10=1;
  if(method==METHOD_OPTIONS && http10<2) http10=2;
  if(method==METHOD_TRACE && http10<2) http10=2;
  switch(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();
     // 如果创建进程失败或为子进程
     // 休眠1秒
     // 目的是让主进程继续创建进程
   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); */
    // 发送给主进程的数据: speed, failed, bytes
     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)
    {
      // 读取数据
      // 格式:speed  failed  bytes
      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=0;
  if(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;
    }

    // 打开socket请求数据
    s=Socket(host,port);  
    // 打开失败
    if(s<0) { failed++;continue;}
    // 发送请求失败
    // failed++
    // 关闭套接字
    if(rlen!=write(s,req,rlen)) {failed++;close(s);continue;}
    // GET
    if(http10==0)
    if(shutdown(s,1)) { failed++;close(s);continue;}
    // 不强制读取服务器回复
    // -f 不读取服务器回复
    if(force == 0)
    {
      /* read all available data from socket */
      // 循环读取数据
    while(1)
    {
        // 超时退出
        if(timerexpired) break;
        // 单次读到1500字节
        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++;
  }
}

5. 总结

webbench 是一个C语言编写的http性能压测试工具,代码非常简结,本人也追求代码的简洁之道。有人统计进,一千行代码中,大概有50- 500个BUG。所以代码精简,不但易于阅读,还能使程序出问题的概率降低。

通过webbench代码的学习,里面包含了:参数设置,进程,管道通信,信号,socket,http知识等。是一个很好的源码学习工具。

 

网站压测工具 Webbench 源码分析 介绍 Webbench是一个在Linux下使用的非常简单的网站压测工具。它的源代码只有500多行,挺值得一看的开源项目。 实现原理 只是简单的fork()出多个子进程模拟客户端去访问设定的URL,测试网站在压力下工作的性能,然后把结果写到管道,让父进程读取并打印到屏幕。 工作流程图 源码分析 执行结果 一些打印信息根据下面的执行结果进行对比 [luxizheng@VM-12-17-centos WebBench-master]$ ./webbench -f -t 10 -c 10 -2 http://ww 阅读详情

相关推荐

深入解析Webbench:从源码看轻量级压测工具的设计精髓

本文深入解析了轻量级Web压力测试工具Webbench的设计精髓。通过对其源码的剖析,揭示了其采用多进程模型与管道通信实现高并发压测的核心架构,并探讨了其高效、简洁的设计哲学与适用场景,为开发者学习网络编程与性能测试提供了宝贵参考。

weixin_29196891的博客 308

用jmeter压测tcp

在工作中有个接口是tcp协议的,然后需要压测一下,就想到jmeter有现成的tcp取样器,百度了一下,压测流程大致和http差不多,需要注意的是tcp请求的一些设置,在此记录一下~

weixin_44857268的博客 7843

【源码剖析】Webbench —— 简洁而优美的压力测试工具

Webbench 是一个古老而著名的网站压力测试工具,简单而实用。如果你不清楚你的网站能承受多大的压力,或者你想分析对比两个网站的性能,webbench 再好用不过了。

Just Coding! 1万+

【免费下载】 TCPBurn:强大的TCP并发压力测试工具

TCPBurn是一个专为并发测试设计的TCP流重放工具,适用于任何支持重放功能的TCP应用。该工具通过模拟真实的网络交互、控制网络延迟以及处理上层协议交互,来实现对目标服务的高并发压力测试。项目主要采用C++进行编写。 ## 新手使用指南及常见问题解决方案 ### 1. 了解基础环境需求 **问题描述**: 新手可能不清楚TCPBurn运行所需的基本系统配置和依赖项。 **解决步骤**: -

gitblog_00193的博客 1439

【逆向实战】Unity游戏资源提取与解密全攻略:从AssetBundle到libil2cpp.so的破解技巧

本文详细介绍了Unity游戏资源提取与解密的完整流程,涵盖从AssetBundle到libil2cpp.so的破解技巧。通过AssetStudio和Il2CppDumper等工具,读者可以学习如何提取未加密资源、处理加密文件,并掌握动态dump技术。文章还提供了自动化脚本编写和常见问题解决方案,帮助逆向工程爱好者高效完成资源提取任务。

weixin_29012765的博客 1046

Win11家庭版如何让Win+R运行CMD默认管理员权限?3种方法实测有效

本文针对Win11家庭版用户,实测了三种让Win+R运行CMD默认获取管理员权限的有效方法。通过分析UAC机制与家庭版功能限制,详细介绍了注册表编辑、快捷方式创建与任务计划程序三种方案的原理、步骤与风险对比,帮助用户根据安全与效率需求选择最佳方案,实现一键高效管理。

sat99的博客 1270

主流压力测试工具推荐

依托压测宝以及完善的产品线,云智慧为用户提供了一站式压测服务,面向云计算时代的复杂应用提供专业性能压测服务,帮助企业客观评估应用性能容量,发现全链路性能瓶颈,对应用架构的调优及架构容量规划提供专业咨询服务,满足企业灵活多变的业务需求。Gatling针对JMeter的不足做了大量改进:在并发性能方面,Gatling使用的Actors模型的性能在高并发的情况下性能大大优于JMeter的Threads,从而使得Gatling在更少的内存和CPU的情况下可以提供同样的测试能力,降低了测试成本;

2301_79535733的博客 995

工业视觉开发者的福音:用C#玩转VisionMaster算子(非方案版完整教程)

本文为工业视觉开发者提供了一份完整的C#与VisionMaster算子二次开发教程,详细介绍了环境配置、算子调用原理、性能优化技巧及实战案例。通过模板匹配和二维码识别等实例,展示了如何高效集成VisionMaster算子到现有框架中,提升工业自动化视觉检测系统的灵活性和性能。

weixin_29280657的博客 270

jmeter TCP接口压力测试

启动jmeter,添加线程组、TCP取样器、察看结果树 1.添加线程组 2.添加TCP取样器 3.添加监听器察看结果树 配置TCP取样器参数信息 1.TCPClient classname:报文格式,分3种: org.apache.jmeter.protocol.tcp.sampler.TCPClientImpl:普通文本传输 org.apache.jmeter.protocol.tcp.sampler.BinaryTCPClientImpl:十六进制报文 org.apache.jmeter.pro

viola_M的博客 1万+

python音频信号分析

声音以具有诸如频率、带宽、分贝等参数的音频信号的形式表示,典型的音频信号可以表示为幅度和时间的函数

MAY的博客 2785

FPS游戏自动枪械识别+压枪(以PUBG为例)

使用Python3.9作为开发环境,实现一个通用的FPS游戏自动检测枪械配件+压枪宏的软件开发思路

weixin_37827742的博客 3万+

开源项目Web Bench 详解,内附视频

开源项目 Web Bench 详解。

Muti-Agent 1630

RK3588 开启多窗口

这样就支持多窗口了。

tzj1058756809的博客 267

深入解析Webbench:从源码看高性能压测工具的设计精髓

本文深入解析了Webbench这一经典高性能压测工具的设计精髓。通过源码分析,揭示了其基于fork()的多进程并发模型、利用管道进行进程间通信以及通过信号机制实现精准计时的核心架构。文章详细阐述了其从请求构建到结果汇总的工作流程,并探讨了其作为轻量级压测利器的适用场景与局限性,为开发者理解高性能服务器测试工具底层原理提供了宝贵参考。

nft7creator的博客 439

华为OD机考双机位A卷 - 流浪地球(Java & Python& JS & C/C++ & GO )

华为OD机考双机位A卷 - 流浪地球(OD上机考试双机位A卷)。提供在线OJ刷题。Java、C++、Python、GO语言、C语言、JavaScript题解,并提供完整思路讲解。

算法大师! 4041

第十五章数据管理成熟度评估【6’】(DAMA-CDGA 2022年以后历年模拟题真题汇总,基本包含所有考点。)

第十五章数据管理成熟度评估【6’】(DAMA-CDGA 2022年以后历年模拟题真题汇总,基本包含所有考点。)

JasonH2021的博客 403

500行代码搞定网站压测:手把手教你用Webbench源码搭建自己的性能测试工具

本文详细解析了Webbench源码,教你如何用500行代码构建高性能压测工具。从多进程架构到HTTP协议实现,再到性能优化和二次开发指南,全面掌握Webbench的核心设计理念与实战技巧,助力开发者快速搭建定制化性能测试方案。

g9h0i1的博客 595

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

压测工具webbench源码分析

转载自http://www.cnblogs.com/xuning/p/3888699.html。     说明:内容绝大来自博主HorstXu,但是也添加了自己的一点理解。 一 我与webbench二三事    Webbench是一个在linux下使用的非常简单的网站压测工具。它使用fork()模拟多个客户端同时访问我们设定的URL,测试网站在压力下工作的性能。Webbench使用C语言编写

LWJ的专栏 886

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

web性能压力测试工具:Webbench 源码分析

前言 Webbench是一个网站压力测试的工具。由Lionbridge公司开发,Webbech的标准测试可以向我们展示服务器的两项内容,分别为每秒钟请求数和每秒钟传输数据量。如果你不清数访问的网站能承受多大的压力,或者对比两个网站的性能可以,考虑使用Webbench或者http_load来测试。 源码下载 webbench源码一共包含两个源文件:socket.c和webbench.c 下载地址: ...

chen1415886044的博客 888

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

网站压测工具Webbench源码分析

网站压测工具Webbench源码分析 一,介绍一下webbench的下载安装过程, http://home.tiscali.cz/~cz210552/webbench.html 这是网站的截图, 把webbench-1.5.tar.gz这个文件下载下来之后解压缩,进入webbench-1.5文件夹,然后执行make,就可以看到文件夹下多了一个可执行程序webbench,

shenwanjiang111的专栏 1415

Web压测工具http_load原理分析

摘要:http_load是一款开源的Web服务器性能测试工具,相比老旧的webbench具有更新频繁、数据统计更全面的优势。它采用单进程并行复用方式,支持校验码检查、超时检测等功能,通过参数控制访问频率、并发量等测试条件。文章详细解析了工具的使用方法、与webbench的性能对比(2946 vs 3006 RPS),并深入剖析其实现原理,包括非阻塞I/O处理、三核心数据结构(连接、URL、定时器)以及创新的拉链式哈希表定时管理机制。最后建议将两款工具配合使用以相互验证测试结果。

nhb687095的博客 721

web性能压力测试工具:WebBench详解

1.Webbench官方主页:http://home.tiscali.cz/~cz210552/webbench.htmlWebbench的官方介绍:Web Bench is very simple tool for benchmarking WWW or proxy servers. Uses fork() for simulating multiple clients and can use ...

竹影映泉的博客 2782

软件压力测试工具Webbench源码分析

网站压测工具Webbench源码分析 原文链接:点击打开链接 Webbench是一个在Linux下使用的非常简单的网站压测工具。它使用fork()模拟多个客户端同时访问我们设定的URL,测试网站在压力下工作的性能。Webbench使用C语言编写,下面是其下载链接: http://home.tiscali.cz/~cz210552/webbench.html Webb

qq_36534818的博客 608

Webbench源码分析

Webbench源码分析 简介Webbench是一个在Linux下使用的非常简单的网站侧压工具。它使用fork()模拟多个客户端同时访问url,测试网站在压力下工作的性能。 工作原理主函数进行必要的准备工作,进入bench开始压测 bench函数使用fork模拟出多个客户端,调用socket并发请求,每个子进程记录自己的访问数据,并切入管道 父进程从管道读取子进程的输出信息 使用alarm函数进行时

没有最好,只有更好! 5847
上一篇: [设计模式]行为模式-解释器(C++描述)
下一篇: 源码分析-简洁的HTTPServer-tinyhttpd
second60
博客等级 码龄9年 155粉丝 88原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值