C++高性能优化编程之如何测量性能(一)

这篇具有很好参考价值的文章主要介绍了C++高性能优化编程之如何测量性能(一)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

系列文章目录

C++高性能优化编程系列
深入理解设计原则系列
深入理解设计模式系列
高级C++并发线程编程

1、为什么要进行性能优化

不好的编程习惯,不重视程序性能测量分析让代码跑的更快,会导致浪费大量的CPU周期、程序响应时间慢以及卡顿,用户满意度下降,进而浪费大量的时间返工去重构本应该一开始就更加高效的代码。性能优化与编码对开发过程而言有着同等的重要性。对于用户而言,性能糟糕的让人无法接受,这个问题的严重程度不亚于出现bug和未实现的特性。

性能优化的目的:是通过改善正确的程序行为使满足客户对处理速度、吞吐量、内存占用以及能耗等各种指标的需求。

2、性能测试的指标是什么

  • 启动时间
    通过测量程序进入main()函数到进入主循环的时间来得到启动时间。
  • 退出时间
    通过测量接收退出命令到程序退出main()的时间来得到退出时间。(退出时间也包含停止所有的线程和所依赖的进程所需的时间)
  • 响应时间
    执行一个命令的平均时间或最长时间。
  • 吞吐量
    在一定的测试负载下,系统在每个时间单位内所执行的操作的平均数。更适合批量处理程序。

3、测量性能及改善变更记录文档

优秀的开发人员都会系统的完善他们的开发任务:

  • 做出的预测都是可测试的,并且记录下预测;
  • 保留代码的变更记录;
  • 可以使用最优秀的工具进行测量;
  • 保留结果的详细笔记。

4、性能测量分析工具的使用

4.1、使用Linux Perf性能分析器进行性能测量分析

介绍一下第一个性能分析器工具Linux Perf性能分析器。这是Linux上流行的性能分析器之一,因为它随大多数发行版一起安装。此性能分析器使用硬件性能计数器和基于时间间隔的采样结合起来,记录正在运行程序的性能分析。它将记录每个样本程序计数器的位置(要执行的指令的地址)和用户正在监控的性能计数器的值。运行该性能分析器后,即可对数据进行分析;样本最多的函数和代码占据大部分执行时间。

值得注意的是,性能分析器在运行时收集指令地址,要将其转换为原始源代码中的行号,必须使用调试信息编译程序。使用两种编译模式组合:optimized(优化)和debug non-optimized(调试非优化) - 调试和优化都被启用。
使用这种选项组合的原因是我们需要分析将在生产环境中运行的相同代码,否则数据大多没有意义。

计数器
cycles(周期):cycles时间是CPU频率的倒数。
instructions(指令):可测量已执行的处理器指令数。
branches(分支):是条件指令,每个if语句和每个带条件的for循环都将至少生成这些指令之一。
branch-misses(分支未命中):
cache-references(缓存引用):统计的是CPU从内存中获取某些东西所需的次数。大多数情况下,这里说的“某些东西”是一段数据,例如字符串中的一个字符。根据处理器和内存的状态,这种获取可能非常快,也可能非常慢。对于慢的,计入cache- misses。
cache-misses(缓存未命中):代码中低效的内存访问,访问速度非常慢。

4.2、使用Google GperfTools性能分析器进行性能测量分析

Gperftools是google开发的一款非常实用的工具集,主要包括:性能优异的malloc free内存分配器tcmalloc;基于tcmalloc的堆内存检测和内存泄漏分析工具heap-profiler,heap-checker;基于tcmalloc实现的程序CPU性能监测工具cpu-profiler.

Goole CPU性能分析器可以使用硬件性能计数器,还需要代码的链接时检测(但不需要编译时检测)。要准备用于性能分析的代码,必须将其与性能分析器的profiler库链接。

与Linux Perf不同的是,Google CPU性能分析器不需要任何特殊的工具来调用程序,必要的代码已连接到可执行文件中。

已检测的可执行文件不会自动开始性能分析。因此,我们必须通过将环境变量CPU PROFILE设置为想要存储结果的文件的文件名来激活性能分析。

5、性能测量微基准测试分析

5.1、使用计时时间测量函数执行时长微基准测试分析

用一个Stopwatch类来测量程序中部分代码的执行时间并分析代码,以下是我编写的一个计时类的代码:

/*
 * @Author: Allen
 * @Date: 2023/5/26
 * @Description: 函数测量计时
 */

#ifndef STUDYTEST_STOPWATCH_H
#define STUDYTEST_STOPWATCH_H

#include <iostream>
#include <chrono>

using namespace std::chrono;
class Stopwatch {
public:
    /*
     * 初始化构造函数
     * _activity:传递功能名称用于log打印
     * */
    explicit Stopwatch(char const* _activity = "Stopwatch"){
        activity_ = _activity;
        start_ = steady_clock::time_point::min();
    }

    ~Stopwatch()= default;

    /*
     * 开始计时
     * */
    void Start(){
        std::cout << "[ " << activity_ << " Start ]" << std::endl;
        start_ = steady_clock::now();
    }

    /*
     * 判断是否已开始计时
     * */
    bool IsStarted() const{
        return start_.time_since_epoch() != steady_clock::duration(0);
    }

    /*
     * 清除计时
     * */
    void Clear(){
        start_ = steady_clock::time_point::min();
    }

    /*
     * 获取间隔时间
     * */
    unsigned long GetMS(){
        if (IsStarted()){
            steady_clock::duration diff;
            diff = steady_clock::now() - start_;
            return (unsigned)(duration_cast<milliseconds>(diff).count());
        }
        return 0;
    }

    /*
     * 停止计时
     * */
    void Stop(){
        unsigned long interval = GetMS();
        std::cout << "[ " << activity_ << " Stop  ] Use Time : " << interval << "ms" << std::endl;
        Clear();
    }

private:
    steady_clock::time_point start_;
    char const* activity_;
};

#endif //STUDYTEST_STOPWATCH_H

引入Stopwatch类使用:

{
   	Stopwatch sw("MyString");
    sw.Start();
    { 
            // 运行的热点函数代码
            // ...
    }
    sw.Stop();
}

运行结果打印:

[ MyString Start ]
[ MyString Stop  ] Use Time : 20ms

5.2、使用Google Benchmark库微基准测试分析

google benchmark主要是对c++中的函数进行基准功能测试。文章来源地址https://www.toymoban.com/news/detail-463540.html

到了这里,关于C++高性能优化编程之如何测量性能(一)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 高性能MySQL实战(三):性能优化

    大家好,我是 方圆 。这篇主要介绍对慢 SQL 优化的一些手段,而在讲解具体的优化措施之前,我想先对 EXPLAIN 进行介绍,它是我们在分析查询时必要的操作,理解了它输出结果的内容更有利于我们优化 SQL。为了方便大家的阅读,在下文中规定类似 key1 的表示二级索引,key_

    2024年02月11日
    浏览(41)
  • 【Linux高性能服务器编程】——高性能服务器框架

      hello !大家好呀! 欢迎大家来到我的Linux高性能服务器编程系列之高性能服务器框架介绍,在这篇文章中, 你将会学习到高效的创建自己的高性能服务器,并且我会给出源码进行剖析,以及手绘UML图来帮助大家来理解,希望能让大家更能了解网络编程技术!!! 希望这篇

    2024年04月25日
    浏览(37)
  • MySQL高性能优化规范建议

    数据库命令规范 数据库基本设计规范 1. 所有表必须使用 Innodb 存储引擎 2. 数据库和表的字符集统一使用 UTF8 3. 所有表和字段都需要添加注释 4. 尽量控制单表数据量的大小,建议控制在 500 万以内。 5. 谨慎使用 MySQL 分区表 6.尽量做到冷热数据分离,减小表的宽度 7. 禁止在表中建

    2024年02月12日
    浏览(35)
  • Kafka高性能集群部署与优化

    Kafka 是由Apache Software Foundation开发的一个分布式流处理平台,源代码以Scala编写。Kafka最初是由LinkedIn公司开发的,于2011年成为Apache的顶级项目之一。它是一种高吞吐量、可扩展的发布订阅消息系统,具有以下特点: 高吞吐量:Kafka每秒可以处理数百万条消息。 持久化:数据存

    2024年02月13日
    浏览(45)
  • 数据库——MySQL高性能优化规范

    所有数据库对象名称必须使用小写字母并用下划线分割 所有数据库对象名称禁止使用 MySQL 保留(如果表名中包含查询时,需要将其用单引号括起来) 数据库对象的命名要能做到见名识意,并且最后不要超过 32 个字符 临时库表必须以 tmp_为前缀并以日期为后缀,

    2024年02月11日
    浏览(86)
  • 读高性能MySQL(第4版)笔记10_查询性能优化(上)

    4.11.1.1. 在存储引擎层完成的 4.11.2.1. 直接从索引中过滤不需要的记录并返回命中的结 4.11.2.2. 在MySQL服务器层完成的,但无须再回表查询记录 4.11.3.1. 在MySQL服务器层完成 4.11.3.2. 需要先从数据表中读出记录然后过滤 4.13.2.1. 使用单独的汇总表 5.5.1.1. 定期清除大量数据时,

    2024年02月08日
    浏览(42)
  • 读高性能MySQL(第4版)笔记12_查询性能优化(下)

    2.3.1.1. 读取行指针和需要排序的字段,对其进行排序,然后再根据排序结果读取所需要的数据行 2.3.1.2. 即需要从数据表中读取两次数据,第二次读取数据的时候,因为是读取排序列进行排序后的所有记录,这会产生大量的随机I/O,所以两次传输排序的成本非常高 2.3.2.1. 先

    2024年02月08日
    浏览(38)
  • Python asyncio高性能异步编程 详解

    目录 一、协程 1.1、greenlet实现协程 1.2、yield 1.3、asyncio 1.4、async await 二、协程意义 三、异步编程 3.1、事件循环 3.2、快速上手 3.3、await 3.4、Task对象 3.5、asyncio.Future对象 3.5、concurrent.futures.Future对象 3.7、异步迭代器 3.8、异步上下文管理器 四、uvloop 五、实战案例

    2024年02月20日
    浏览(48)
  • 《Linux高性能服务器编程》笔记04

    本文是读书笔记,如有侵权,请联系删除。 参考 Linux高性能服务器编程源码: https://github.com/raichen/LinuxServerCodes 豆瓣: Linux高性能服务器编程 I/O复用使得程序能同时监听多个文件描述符,这对提高程序的性能至关重要。通常,网络程序在下列情况下需要使用I/0复用技术: 客户

    2024年01月21日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包