C++(Qt)软件调试---VS性能探查器(27)


### 文章目录

  • [@[toc]](#文章目录 @[toc] 1 概述🐜 2 VS工具说明 2.1 使用场景 2.2 工具适用项目 3 CPU使用率 4 内存分析 4.1 调试模式下分析内存 4.2 非调试模式下分析内存 5 相关地址🐐)
  • [1 概述🐜](#文章目录 @[toc] 1 概述🐜 2 VS工具说明 2.1 使用场景 2.2 工具适用项目 3 CPU使用率 4 内存分析 4.1 调试模式下分析内存 4.2 非调试模式下分析内存 5 相关地址🐐)
  • [2 VS工具说明](#文章目录 @[toc] 1 概述🐜 2 VS工具说明 2.1 使用场景 2.2 工具适用项目 3 CPU使用率 4 内存分析 4.1 调试模式下分析内存 4.2 非调试模式下分析内存 5 相关地址🐐)
  • [2.1 使用场景](#文章目录 @[toc] 1 概述🐜 2 VS工具说明 2.1 使用场景 2.2 工具适用项目 3 CPU使用率 4 内存分析 4.1 调试模式下分析内存 4.2 非调试模式下分析内存 5 相关地址🐐)
  • [2.2 工具适用项目](#文章目录 @[toc] 1 概述🐜 2 VS工具说明 2.1 使用场景 2.2 工具适用项目 3 CPU使用率 4 内存分析 4.1 调试模式下分析内存 4.2 非调试模式下分析内存 5 相关地址🐐)
  • [3 CPU使用率](#文章目录 @[toc] 1 概述🐜 2 VS工具说明 2.1 使用场景 2.2 工具适用项目 3 CPU使用率 4 内存分析 4.1 调试模式下分析内存 4.2 非调试模式下分析内存 5 相关地址🐐)
  • [4 内存分析](#文章目录 @[toc] 1 概述🐜 2 VS工具说明 2.1 使用场景 2.2 工具适用项目 3 CPU使用率 4 内存分析 4.1 调试模式下分析内存 4.2 非调试模式下分析内存 5 相关地址🐐)
  • [4.1 调试模式下分析内存](#文章目录 @[toc] 1 概述🐜 2 VS工具说明 2.1 使用场景 2.2 工具适用项目 3 CPU使用率 4 内存分析 4.1 调试模式下分析内存 4.2 非调试模式下分析内存 5 相关地址🐐)
  • [4.2 非调试模式下分析内存](#文章目录 @[toc] 1 概述🐜 2 VS工具说明 2.1 使用场景 2.2 工具适用项目 3 CPU使用率 4 内存分析 4.1 调试模式下分析内存 4.2 非调试模式下分析内存 5 相关地址🐐)
  • [5 相关地址🐐](#文章目录 @[toc] 1 概述🐜 2 VS工具说明 2.1 使用场景 2.2 工具适用项目 3 CPU使用率 4 内存分析 4.1 调试模式下分析内存 4.2 非调试模式下分析内存 5 相关地址🐐)
更多精彩内容
👉内容导航 👈
👉C++软件调试 👈

1 概述🐜

软件开发中程序性能优化、性能瓶颈排查对开发人员来说是必不可少的技能。

常见的性能优化包括CPU使用率、内存使用率、内存泄漏、文件IO等。

linux下的perf工具功能非常强大,但是可惜不支持Windows;而windows中VS也提供了类似的工具,本文主要讲解VS性能探查器常用工具的基本使用和注意事项。

Visual Studio的性能探查器是开发人员用于检测和优化应用程序性能的重要工具。

不同版本的VS提供的性能探查器有一定区别,旧版本的VS中性能探查器包含的工具种类要少一些。

性能探查器中提供的工具包括:

VS提供的这些工具其中部分适用于C++程序开发,部分不适应。

演示环境:

环境 版本
系统 Windows11
IDE VS2017、VS2022

2 VS工具说明

2.1 使用场景

性能工具 说明 何时使用此工具?
CPU 使用率 显示 CPU 耗用时间的位置。 • 开始调查一般的性能问题。 • 调查高服务器 CPU 使用率。 • 调查 DevOps 场景,例如订单无法发送到零售网站的情况。 • 优化 CPU 使用率。 • 调查 API 调用中的延迟。
火焰图 在 CPU 使用率工具中查看,该工具提供调用树的备用可视化效果。 调查 API 调用中的延迟
热路径 在 CPU 使用率工具中查看,该工具显示应用程序耗用大部分 CPU 时间的位置。 调查 API 调用中的延迟
内存使用率 显示应用内存以查找内存泄漏等问题。 • 优化内存使用情况 • 调查 UI 冻结 • 调查可疑内存泄漏(本机代码)
.NET 对象分配 显示 .NET 对象的分配位置以及有关垃圾回收的信息。 • 优化 .NET 内存使用情况 • 分析垃圾回收
检测 显示确切的调用计数和调用时间。 • 需要类似于 CPU 使用率的工具,但希望根据壁挂时钟时间确定在函数中花费的确切调用计数和时间。 • 你希望确定被阻止的时间,例如等待锁所用的时间。 • 注意:此工具需要额外的开销。
文件 I/O 显示文件 I/O 操作以及它们花费的时间和要处理的数据量。 调查 UI 冻结
性能提示 显示与代码交互时性能信息的快速度量。 调试时,你希望查看上一步操作(或断点)到当前步骤或断点之间的运行时间。
事件查看器 显示 HTTP 请求、日志消息和异常。 • 调查 API 调用中的延迟 • 调查远程 Web 服务器上运行缓慢的应用程序
.NET Async 显示 .NET 应用中的异步/await 使用情况。 调查怀疑异步代码存在的性能问题。
.NET 计数器 .NET 计数器的实时报告。 • 开始调查常规性能问题。 • 需要跟踪基于 .NET 计数器的指标,例如每秒异常数、垃圾回收和 CPU 利用率。
Database 显示数据库查询性能。 调查使用 ADO.NET 或 Entity Framework Core 的数据库查询的性能。
GPU 使用情况 显示 Direct3D 应用的高级硬件使用情况。 检查应用性能是受 CPU 限制还是受 GPU 限制。
应用程序时间线 显示 XAML 应用的 UI 性能。 调查 XAML 应用中的 UI 性能,例如呈现帧所用的时间。
IntelliTrace 调试器工具可用于记录事件,并检查应用程序在不同执行点的状态。 你需要一个工具来检查应用程序在不同点的状态,而不仅仅是当前应用程序状态。

2.2 工具适用项目

性能工具 .NET C/C++ UWP ASP.NET/ASP.NET Core
CPU 使用率
内存使用率
.NET 对象分配
检测
文件 I/O
性能提示
事件查看器
.NET Async
.NET 计数器 是(仅限 .NET Core/5 及更高版本) 是(仅限 ASP.NET Core)
Database 是(仅限 .NET Core/5 及更高版本) 是(仅限 ASP.NET Core)
GPU 使用情况
应用程序时间线 是 (XAML)
性能资源管理器
IntelliTrace 仅适用于带有 Visual Studio Enterprise 的 .NET 仅适用于带有 Visual Studio Enterprise 的 .NET 仅适用于带有 Visual Studio Enterprise 的 .NET

3 CPU使用率

  1. 创建一个工程,这里我创建的是一个Qt工程;

  2. 添加如下所示代码:

    cpp 复制代码
    #include "QtWidgetsApplication3.h"
    #include <vector>
    #include <list>
    
    using namespace std;
    
    void fun1()
    {
        vector<int> arr;
        for (int i = 0; i < 10000000; i++)
        {
            arr.push_back(i);
        }
    }
    
    void fun2()
    {
        list<int> arr;
        for (int i = 0; i < 10000000; i++)
        {
            arr.push_back(i);
        }
    }
    void fun3()
    {
        vector<int> arr;
        arr.reserve(10000000);
        for (int i = 0; i < 10000000; i++)
        {
            arr.push_back(i);
        }
    }
    
    QtWidgetsApplication3::QtWidgetsApplication3(QWidget *parent)
        : QWidget(parent)
    {
        ui.setupUi(this);
    
        fun1();
        fun2();
        fun3();
    }
    
    QtWidgetsApplication3::~QtWidgetsApplication3()
    {}
  3. 选择【Debug】模式,【调试】【性能探查器】或者直接按快捷键【Alt + F2】打开;

    • 如果是【Release】模式,需要选择项目,右键【属性】【链接器】【调试】,将生成调试信息项选为【生成调试信息 (/DEBUG)】,用于生成pdb符号表,否则测试结果没办法看。
  4. 勾选【CPU使用率】,然后点击【开始】按键;

  5. 编译运行起来后就开始检测CPU使用率了,当需要停止检测时直接退出程序或者点击【停止收集】就能自动生成分析结果了;

  6. 如下图所示可以看出在【热路径】栏中CPU占用高的函数为fun2(),或者点击【打开详细信息】更容易观看;

  7. 如下图所示,可选择【调用方/被调用方】、【调用树】、【模块】、【函数】、【火焰图】几种显示视图;

    • 点击调用方三个矩形模块可以切换调用函数;
    • 调用树 适用于函数调用栈不深的情况,对于Qt开发的程序一般函数调用栈都比较深,使用调用树视图很不方便观看;
    • 模块视图可适用于分析使用到的动态库性能;
    • 使用较多的是函数视图,可以直接看哪个函数CPU占用高,然后双击函数名打开所在代码;
    • 火焰图是CPU性能分析常见视图,在使用perf时常常使用火焰图,但是在VS2022中才有,旧版本的VS没有火焰图。
  8. 鼠标在生成的报告 上右键可以选择保存报告,最好将此时的代码、可执行程序、pdb符号表保存到一起,用于后续回看。

  9. 如同所示可分析不同线程的CPU占用率。

  10. 如下图所示,在不同视图中鼠标右键打开菜单可以切换使用其它视图显示。

  11. 使用火焰图时如下所示,纵轴为函数调用堆栈,横轴为函数占用CPU时长,函数执行越耗时,越宽。

4 内存分析

使用内存分析工具可以分析C++程序出现的内存泄露等问题。

4.1 调试模式下分析内存

例如控制台程序,可能运行后立即就退出了,这种情况就需要使用调试模式来分析内存泄漏。

注意:

  1. 最好使用debug模式,如果使用release模式那就需要设置生成pdb符号表。
  2. vs的内存分析工具不使用于大型项目,并且对程序性能影响较大,执行过程中会在C:\Users\MHF\AppData\Local\Temp文件夹中生成大量数据,几分钟可能就几个G或者几十个G,所以如果C盘内存不足也会导致分析失败或者分析速度非常慢。
  1. 创建一个C++工程,代码如下所示:

    cpp 复制代码
    #include <iostream>
    
    void fun()
    {
        int* p = new int[10000];
        for (int i = 0; i < 10000; i++)
        {
            p[i] = i;
        }
    }
    
    void fun1()
    {
        int* p = new int[10000];
        for (int i = 0; i < 10000; i++)
        {
            p[i] = i;
        }
        delete[] p;
    }
    int main()
    {
        for (int i = 0; i < 100; i++)
        {
            fun();
            fun1();
        }
        return 0;
    }
  2. 如图所示,在需要分析内存的代码段前后打上断点,然后按F5开始调试;

  3. 如图所示,在命中第一个断点后,进入【诊断工具】,选择【内存使用率】,点击【堆分析】;

  4. 然后点击【截取快照】,就会生成内存镜像;

  5. 再按F5继续执行,命中第二个断点,然后点击【截取快照】就会生成第二个内存快照;

  6. 可以看出第二个内存快照相对于第一个出现了内存增长;

  7. 双击第二个内存快照;就会出现内存使用窗口;

  8. 然后双击使用的内存项,就会出现分配内存的堆栈,如下所示,在fun函数中,文件第8行分配的内存出现内存泄漏;

4.2 非调试模式下分析内存

  1. 创建一个Qt程序;添加一个PushButton,在按键槽函数中分配内存不释放;

  2. 然后点击【调试】【性能探查器】;

  3. 勾选【内存使用率】,点击【开始】;

  4. 如下所示,程序启动后,点击【截取快照】,然后点击操作程序分配内存,再次点击【截取快照】,点击【停止收集】或者直接退出程序,当生成分析报告后可看出第二层快照存在内存增长,点击第二层快照就可以看见内存泄漏的堆栈位置了。

5 相关地址🐐



相关推荐
我不是代码教父2 小时前
[原创](Modern C++)现代C++的关键性概念: 流格式化
c++·字符串格式化·流格式化·cout格式化
利刃大大2 小时前
【回溯+剪枝】找出所有子集的异或总和再求和 && 全排列Ⅱ
c++·算法·深度优先·剪枝
子燕若水2 小时前
mac 手工安装OpenSSL 3.4.0
c++
*TQK*2 小时前
ZZNUOJ(C/C++)基础练习1041——1050(详解版)
c语言·c++·编程知识点
ElseWhereR3 小时前
C++ 写一个简单的加减法计算器
开发语言·c++·算法
*TQK*3 小时前
ZZNUOJ(C/C++)基础练习1031——1040(详解版)
c语言·c++·编程知识点
※DX3906※4 小时前
cpp实战项目—string类的模拟实现
开发语言·c++
萌の鱼4 小时前
leetcode 2080. 区间内查询数字的频率
数据结构·c++·算法·leetcode
xianwu5436 小时前
反向代理模块jmh
开发语言·网络·数据库·c++·mysql
行十万里人生7 小时前
Qt事件处理:理解处理器、过滤器与事件系统
开发语言·git·qt·华为od·华为·华为云·harmonyos