- 语言经验 - 《使用google profiler 对c++应用进行性能热点分析》

本文属于专栏《构建工业级QPS百万级服务》​​​​​


性能优化,是工业应用中的重要一环。因为当我们的重要目的之一是盈利时,那么成本就十分重要。而性能优化的前提是,我们知道哪一部分功能,是最耗费资源的,才能用20%的精力去解决80%的问题。

在我使用过热点分析的工具中,最喜欢的是google profiler,因为它的信息足够详细。这里我们基于《c++11获取系统时间最快的方式》增加了3行代码,来测试这段逻辑的性能。增加代码分别是第8,51,58行

cpp 复制代码
  1 #include <iostream>
  2 #include <chrono>
  3 #include <ctime>
  4 #include <sys/time.h>
  5 #include <thread>
  6 #include <vector>
  7 #include <functional>
  8 #include <gperftools/profiler.h>
  9
 10 using namespace std;
 11 using namespace std::chrono;
 12
 13 const int TEST_TIMES = 1000 * 1000 * 10;
 14
 15 long long getCurrentTimeByClockGetTime() {
 16     struct timespec spec;
 17     clock_gettime(CLOCK_REALTIME, &spec);
 18     return spec.tv_sec * 1000LL + spec.tv_nsec / 1000000;
 19 }
 20
 21 long long getCurrentTimeByGetTimeOfDay() {
 22     struct timeval tv;
 23     gettimeofday(&tv, NULL);
 24     return tv.tv_sec * 1000LL + tv.tv_usec / 1000;
 25 }
 26
 27 long long getCurrentTimeByChrono() {
 28     return duration_cast<milliseconds>(high_resolution_clock::now().time_since_epoch()).count();
 29 }
 30
 31 void testFunction(const std::function<void()>& testFunc, const std::string& testName) {
 32     long long start = getCurrentTimeByChrono();
 33     for (int i = 0; i < TEST_TIMES; ++i) {
 34         testFunc();
 35     }
 36     long long end = getCurrentTimeByChrono();
 37     cout << "Using " << testName << " in thread " << this_thread::get_id() << ": " << end - start << " ms\n";
 38 }
 39
 40 void testMultiThread(int thread_num, const std::function<void()>& testFunc, const std::string& testName) {
 41     vector<thread> threads;
 42     for (int i = 0; i < thread_num; ++i) {
 43         threads.emplace_back(testFunction, testFunc, testName);
 44     }
 45     for (auto& t : threads) {
 46         t.join();
 47     }
 48 }
 49
 50 int main() {
 51     ProfilerStart("test.prof");
 52     testMultiThread(1, getCurrentTimeByChrono, "chrono::high_resolution_clock");
 53     testMultiThread(10, getCurrentTimeByChrono, "chrono::high_resolution_clock");
 54     testMultiThread(1, getCurrentTimeByGetTimeOfDay, "gettimeofday");
 55     testMultiThread(10, getCurrentTimeByGetTimeOfDay, "gettimeofday");
 56     testMultiThread(1, getCurrentTimeByClockGetTime, "clock_gettime");
 57     testMultiThread(10, getCurrentTimeByClockGetTime, "clock_gettime");
 58     ProfilerStop();
 59 }

我们还需要执行一下命令,来安装google profiler。其中git仓库的目录和上面文件同级

当前目录会生成文件test.prof,然后执行命令

  • pprof --pdf a.out test.prof > test.pdf(pprof通过命令sudo yum install gperftools gperftools-devel安装)

此时目录结构如下

test.pdf打开如下图示例,可以看到每个函数的调用频率,以及顺序依赖关系。其统计原理就是等间隔时间采样,确认当前时间正在执行的函数栈,然后对每个函数栈统计运行次数。如下图中最大的方块syscall,是chrono调用的,这就是chrono慢的原因,因为它会在内核态和用户态之间切换。整个应用的执行过程37.7%的时间,都在执行该函数。

相关推荐
setary03012 分钟前
c++泛型编程之Typelists
开发语言·c++
u0104058362 分钟前
Java应用的链路追踪:实现分布式跟踪
java·开发语言·分布式
这是个栗子6 分钟前
【API封装参数传递】params 与 API 封装
开发语言·前端·javascript·data·params
27669582927 分钟前
vercel 安全检测逆向 x-vercel-challenge-solution
开发语言·python·solution·vercel-solution·x-vercel·vercel逆向·ensun
傻乐u兔8 分钟前
C语言初阶————调试实用技巧1
c语言·开发语言
Sammyyyyy17 分钟前
Gemini CLI 进阶:构建安全的MCP连接与验证策略
开发语言·ai·ai编程·servbay
老蒋每日coding17 分钟前
驾驭并发之力:Go语言构建高可用微服务完全指南
开发语言·微服务·golang
努力学习的小洋21 分钟前
Python训练打卡Day4:缺失值处理
开发语言·python
郝学胜-神的一滴21 分钟前
Python类属性与实例属性详解及MRO算法演进
开发语言·python·程序人生·算法
一颗青果22 分钟前
短线重连代码实现
开发语言·网络·c++