一、应用场景
性能测试的应用场景除了大规模计算、寻找瓶颈之外,其实对于不停服的服务端程序(包括Web服务和CS服务端等),更具有实战意义。在此类的实际场景中,经常存在以下几个问题: 1、服务端调优,需要找到性能瓶颈,而往往这种瓶颈并不是随时出现,而是随机出现的。 2、问题异常的发现,比如偶尔会有突然的报警或者CPU内存等异常升高。 3、多方比较,与同类型或者友商类似软件的性能比较分析 4、设计验证,也就是开发架构时的设想与实际上线后有何差别,差别有多大。 这些都需要一些量化指标,而这些量化指标,就需要通过测试工具来完成,有些测试工具可以在外面提供相关的测试,比如压力测试等,但开发者更需要在这种情况下,到底是哪些模块甚至是哪些函数成为了焦点所在。同时,服务端基本上是不允许随意停服的,而且往往测试工具也会带来性能的损耗,这就需要一种方式和手段来实现动态的操作测试。
二、实际应用
这里使用在Linux下的信号来处理这种问题,通过向程序发送指定的信号来决定性能测试代码的启停,获取对关心时段的性能焦点的数据分析,先看一个例子:
#include <google/profiler.h>
#include <iostream>
#include <unistd.h>
#include <signal.h>
using namespace std;
void t1()
{
int i = 0;
while (i < 1000)
{
i++;
}
}
void t2()
{
int i = 0;
while (i < 2000)
{
i++;
}
}
void t3()
{
for (int i = 0; i < 100000000; ++i)
{
t1();
t2();
std::cout<<"once t3"<<std::endl;
//sleep(1);
}
}
int bQuit = false;
static void setGperfSig(int num)
{
static bool open = false;
if (num != SIGUSR1) {
return;
}
if (!open)
{
open = true;
ProfilerStart("sigtest.prof");
std::cout << "ProfilerStart OK" << std::endl;
}
else
{
open = false;
std::cout << "ProfilrerStop OK" << std::endl;
ProfilerStop();
bQuit = true;
}
}
int main(int argc, const char* argv[])
{
signal(SIGUSR1, setGperfSig);
int click = 0;
while (!bQuit)
{
t3();
std::cout << "second data is:" << ++click << std::endl;
sleep(1);
}
return 0;
}
上面的代码有个小细节,如果加入延时后,可能无法快速测试出结果,使用前面的方法来编译操作:
f:~/testtool$ g++ -o sigtest sigtest.cpp -lprofiler -lunwind
//设置一下库的路径
export LD_LIBRARY_PATH=/usr/local/lib
export PATH=$PATH:/usr/local/bin
运行程序并启动、关闭性能测试(启动和停止间隔一段时间)
//启动程序
f:~/testtool$ ./sigtest
//显示进程ID
f:~/testtool$ ps -ef|grep sigtest
fpc 4838 3202 80 10:44 pts/0 00:00:04 ./sigtest
fpc 4843 2213 0 10:44 pts/1 00:00:00 grep --color=auto sigtest
//发送启动测试信号
f:~/testtool$ kill -s SIGUSR1 4838
//间隔一段时间再次发送
f:~/testtool$ kill -s SIGUSR1 4838
通过命令得到测试结果是:
f:~/testtool$ pprof --text sigtest sigtest.prof
Using local file sigtest.
Using local file sigtest.prof.
Total: 558 samples
433 77.6% 77.6% 433 77.6% __write
80 14.3% 91.9% 80 14.3% t2
43 7.7% 99.6% 43 7.7% t1
1 0.2% 99.8% 1 0.2% __nss_database_lookup
1 0.2% 100.0% 1 0.2% fflush
0 0.0% 100.0% 433 77.6% _IO_do_write
0 0.0% 100.0% 433 77.6% _IO_file_overflow
0 0.0% 100.0% 433 77.6% _IO_file_write
0 0.0% 100.0% 558 100.0% __libc_start_main
0 0.0% 100.0% 558 100.0% _start
0 0.0% 100.0% 558 100.0% main
0 0.0% 100.0% 433 77.6% std::endl
0 0.0% 100.0% 1 0.2% std::operator<<
0 0.0% 100.0% 1 0.2% std::ostream::flush
0 0.0% 100.0% 433 77.6% std::ostream::put
0 0.0% 100.0% 558 100.0% t3
这是一个基本的小例子,通过它可以明白整个类似服务端性能测试的一个基本方式和过程,对一些小的细节不用过分的纠结,真正遇到后,自然会明白。不在真实的环境中去测试,就不是真正的性能测试,所以这里以掌握原理和方法为根本,这才是最重要的。
三、总结
做c++/C开发的人越来越少,虽然减少的速度不快了,但仍不能掩饰后继人才不断减少的尴尬,不过这并不代表C/C++没有未来,在很多场景下,都还是需要C/C++来搞定的。比如现在正火的元宇宙,其中的VR等还是C/C++占有很大比重的。学习好C/C++不光是要会它,更要会调教它。通过不同的工具来发现写好的程序的优劣和问题。俗话说,工欲善其事,必先利其器。而gperftools就是这样一把工具,它能让C/C++的程序变得更能够从宏观上把握问题的部分,查找瓶颈,定位问题。好用不好用,试试就知道了,这本来就是一个“小马过河”的问题。
|