- 语言经验 - 《使用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%的时间,都在执行该函数。

相关推荐
Source.Liu18 小时前
【LibreCAD】 RS_Units 类完整解析
c++·qt·rust
JIngJaneIL18 小时前
基于Java酒店预约系统(源码+数据库+文档)
java·开发语言·数据库·vue.js·spring boot
编程小Y19 小时前
php.ini 的核心作用与全面解析
开发语言·php
曹牧19 小时前
Java:List<Map<String, String>>转换为字符串
java·开发语言·windows
我是一棵无人问荆的小草19 小时前
编码演变史
开发语言·c++
偶像你挑的噻20 小时前
2.Qt-基础核心以及信号与槽
开发语言·qt
potato_may20 小时前
CC++ 内存管理 —— 程序的“五脏六腑”在哪里?
c语言·开发语言·数据结构·c++·内存·内存管理
饕餮怪程序猿20 小时前
A*算法(C++实现)
开发语言·c++·算法
观音山保我别报错20 小时前
列表,元组,字典
开发语言·python
**蓝桉**20 小时前
数组的执行原理,java程序的执行原理
java·开发语言