Visual Studio2022 Profile 工具使用

news2024/11/25 0:53:13

本篇研究下Visual Studio自带的性能分析工具,针对C++代码,基于Visual Studio2022


文章目录

  • CPU使用率
  • 检测
  • 并发可视化工具
    • 使用率视图
    • 线程视图
    • 内核视图
    • 并发可视化工具SDK
  • 参考资料


CPU使用率

对于CPU密集型程序,我们可以通过分析程序的CPU使用率,找到程序的瓶颈,Visual Studio原生提供了对于CPU使用情况的诊断工具,具体使用方法如下:

  1. 在 Visual Studio 里打开我们的程序,在我们想分析的函数/代码块的起始位置和结束位置打上断点,比如这里我们想分析的是 getSum() 这个函数。

  2. 调试状态下运行我们的程序,然后打开诊断工具窗口(调试>窗口>显示诊断工具)

  3. 之后可以在诊断工具里,设置选择工具,选择是否查看 CPU使用率和内存使用

  4. 当程序运行到一个断点时,打开CPU 使用率下的记录 CPU 配置文件,之后就会开始记录CPU使用情况

  5. 继续执行我们的代码,然后程序运行到我们的第二个断点处,这是点开CPU使用率,就可以看到CPU使用率相关的信息了。

    (1)CPU 总计:表示该函数函数体和调用的其他函数的总的CPU计数,及占比
    (2)自CPU:表示该函数函数体本身的CPU计数,及占比
    (3)排名靠前的函数:按自CPU计数从大到小排列,这里 func1 函数自CPU 5152(99.52%)
    (4)热路径:CPU计数最大部分的调用树,上面可以看到是 getSum 中调用了 func1

  6. 这里可以打开CPU 使用率的详细信息窗口,或者点击上面图中任意函数,导航到对应位置,这里视图默认显示是调用树,下面代码中会在左侧显示每一行代码的CPU计数。
    在这里插入图片描述

  7. 我们可以选择视图为调用方/被调用方,选择对应的函数,当前函数就是我们选择的函数,可以看到调用函数就是调用当前函数的函数,调用的函数就是当前函数调用到的一些函数

  8. 也可以选择火焰图视图


检测

上面的CPU使用率是通过采样的方式得到,定时去检查CPU的调用堆栈,好处是不会产生大的开销,而检测是通过工具将代码注入到可捕获计时信息的二进制文件中,或通过使用hook在应用程序运行期间收集和发出精确计时和调用计数信息。相对于采样的方式,检测方法开销较大,但检测可提供更确切的调用计数和精确计时。

Visual Studio也提供了原生的检测工具,但对C++程序只能进行静态检测,具体步骤如下:

  1. 首先编译好的目标文件,在链接时需要加上 -PROFILE 选项
  2. 调试 > 性能探查器,打开性能探查器
    .
  3. 首先选择目标,这里选择启动项目,也可以选择链接好的可执行文件,选择检测选项,点击开始。
  4. 等程序运行结束或手动停止检测就会输出包含函数计时的报告
  5. 添加用户标记,这个功能目前还有问题,见下图,等修复好了更新

并发可视化工具

这里简单介绍下如何使用 Visual Studio 提供的并发可视化工具和相关的SDK。

并发可视化工具的使用比较简单,分析 > 并发可视化工具 > 从当前项目开始/启动新进程,启动新进程的话就选择我们要检测的 .exe 文件。

程序运行完之后就会输出报告。

使用率视图

使用率输出进程使用的平均逻辑核心数,这里逻辑核心数上限是 12 那么实际核心数就是 6,如果两个内核在某一给定时间段内均以 50% 的使用率运行,则此视图将显示使用一个逻辑内核。

CPU 使用率图颜色:

  • 绿色表示系统中当前进程的逻辑内核使用率
  • 浅灰色表示系统上其他进程的逻辑内核利用率。如果 CPU 图中的浅灰色百分比过高,则表示其他进程已使系统负载过重,你的进程可能会被这些进程抢占资源。若要减少其他进程使用的逻辑内核数,请减少系统上运行的逻辑内核数。
  • 深灰色表示系统进程的逻辑内核消耗。无法直接控制这部分逻辑内核消耗,但由于这些消耗会影响用户进程可以使用的逻辑内核情况,因此了解这些消耗何时出现非常有用。
  • 白色表示系统上未使用逻辑内核的可用性。如果可以找到更多的并行机会,这些核心则可用于你的进程。

线程视图

左上角选项卡选择线程视图

线程视图上半部分是时间线,时间线显示主计算机上的进程与所有物理磁盘设备中的所有线程的活动。它还显示 GPU 活动和标记事件。

在时间线上,X 轴上是时间,y 轴上是几个通道:

  • 系统上每个磁盘驱动器两个 I/O 通道,一个通道用于读取,另一个用于写入
  • 进程中每个线程一个通道
  • 标记通道(如果跟踪中存在事件标记)。标记通道最初出现在生成这些事件的线程通道下。
  • GPU 通道。

最初,线程按创建顺序进行排序,以便主应用线程处于第一位。在“排序依据”下拉列表中选择另一个选项,以按另一种标准(例如“执行”)对线程进行排序。

时间线的颜色指示线程在给定时间的状态”

  • 绿色段表示已在执行
  • 红色段指示已因同步而受阻
  • 黄色段指示已被抢占
  • 紫色段指示已参与设备 I/O

左侧有线程通道,停在通道名称处时,将显示给定线程的开始函数。并发可视化工具可检测到多种线程。下表列出了最常用的线程类型。

线程描述
主线程启动应用的线程
工作线程由应用程序主线程创建的线程
CLR工作线程由公共语言运行时(CLR)创建的工作线程
调试器帮助程序由 Visual Studio 调试器创建的帮助线程
ConRT 线程由 Microsoft 并发运行时创建的线程
GDI线程由GDIPlus创建的线程
OLE/RPC 线程作为 RPC工作线程创建的线程
RPC作为RPC线程创建的线程
Winsock 线程作为 Winsock 线程创建的线程
线程池由 CLR 线程池创建的线程

内核视图

并发可视化工具里还有一个内核视图,显示线程执行如何映射到逻辑处理器核心。

与留在同一逻辑核心上的切换相比,跨核心上下文切换要花费更多的开销和性能。在上下文切换过程中,将保存并恢复处理器寄存器,执行操作系统内核代码,重新加载转换旁视缓冲项,并刷新处理器管道。因为缓存数据对其他核心上的此线程无效,所以跨核心上下文切换可能比其他上下文切换开销更大。相比之下,如果某个线程上下文切换到之前运行过的该线程的核心上,则有用的数据可能仍在缓存中。当跨核心上下文切换因试图管理线程关联而有所增加且性能出现下降时,请考虑是否要解决这一问题。首先消除线程关联,然后观察由此导致的跨核心行为。

下表描述了图例元素。

元素定义
线程名显示上一个内核时间线中线程的颜色,以及该线程的名称
跨核心上下文切换也从一个逻辑内核切换到另一个逻辑内核的线程的上下文切换数。 不区分从一个处理器芯片跨到另一个芯片的跨核心上下文切换,以及留在同一芯片上的跨核心上下文切换。
上下文切换总数采样期间给定线程的上下文切换总数。 每次线程更改上下文(例如从执行到同步)时,将进行一次上下文切换计数。
跨越核心的上下文切换所占的百分比通过跨核心上下文切换数除以上下文切换总数计算出的百分比。 此百分比越高,此特定线程的性能上的跨核心上下文切换的开销的整体效果越大。

并发可视化工具SDK

这里介绍一个简单的应用,给我们想要关注的函数部分/代码段打上标记,这样在线程视图中,就能看到对应标记的范围了。
对于带解决方案的应用,直接 分析 > 并发可视化工具 > 将 SDK 添加到项目中,然后在项目中 #include <cvmarkersobj.h>,然后使用对应的命名空间 using namespace Concurrency::diagnostic

然后我们可以添加标记通道,创建对应的对象 marker_series series; 在对应的标记通道中,可以加入一个标志范围,delete 就可以结束这个范围,示例代码如下。

#include <iostream>
#include "cvmarkersobj.h"

#define MAX 10000

using namespace Concurrency::diagnostic;

void func1(int& sum) {
    for (int i = 0; i < MAX; i++)
		sum += i;
}

int getSum() {
	int sum = 0;
	for (int i = 0; i < 1000000; i++)
		func1(sum);
	return sum;
}


int main()
{
	marker_series series;
	span* flagSpan = new span(series, 1, _T("flag span"));
	series.write_flag(_T("Here is the flag."));
	int ans = getSum();
	delete flagSpan;

	std::cout << ans << std::endl;

	int ans2 = getSum();
	std::cout << ans2 << std::endl;
}

下面是对应的并发可视化工具视图,可以看到多了一个通道,同时有对应的标志区间。

当然我们也可以创建多个通道。

	marker_series flagSeries(_T("flag series"));
	span* flagSeriesSpan = new span(flagSeries, 1, _T("flag span"));
	flagSeries.write_flag(1, _T("flag"));
	// Sleep to even out the display in the Concurrency Visualizer.
	int ans = getSum();
	Sleep(50);
	delete flagSeriesSpan;
	std::cout << ans << std::endl;

	marker_series messageSeries(_T("message series"));
	span* messageSeriesSpan = new span(messageSeries, 1, _T("message span"));
	messageSeries.write_message(1, _T("message"));
	// Sleep to even out the display in the Concurrency Visualizer.
	int ans2 = getSum();
	Sleep(50);
	delete messageSeriesSpan;
	std::cout << ans2 << std::endl;

这样在视图中就可以看到多个通道和标记区间。


参考资料

通过分析 CPU 使用情况衡量应用程序性能(C#、Visual Basic、C++、F#)
了解探查器性能收集方法
在 Visual Studio(C#、C++、Visual Basic、F#)中检测 .NET 应用程序
内核视图
使用并发可视化工具标记 SDK
“使用率”视图
并发可视化工具中的线程视图

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2224642.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

系统架构设计师教程 第2章 2.5 计算机网络 笔记

2.5计算机网络 ★☆☆☆☆ 2.5.1网络的基本概念 1.计算机网络的发展 计算机网络发展&#xff0c;其大致经历了诞生、形成、互联互通和高速发展等4个阶段。 2.计算机网络的功能 1)数据通信 数据通信是依照一定的通信协议&#xff0c;利用数据传 输技术在两个通信结点之间传…

【Spring Boot】元注解

元注解 1.元注解1.1 Target1.2 Retention1.3 Inherited1.4 Documented1.5 interface 2.自定义注解2.1 创建自定义注解类2.2 实现业务逻辑2.3 使用自定义注解 1.元注解 元注解就是定义注解的注解&#xff0c;是 Java 提供的用于定义注解的基本注解。 注解 说明 Retention是注解…

linux中级(NFS服务器)

NFS&#xff1a;用于在NNIX/Linux主机之间进行文件共享的协议 流程&#xff1a;首先服务端开启RPC服务&#xff0c;并开启111端口&#xff0c;服务器端启动NFS服务&#xff0c;并向RPC注册端口信息&#xff0c;客户端启动RPC&#xff0c;向服务器RPC服务请求NFS端口&#xff0…

Matlab数字信号处理——基于改进小波变换的图像去噪方法(7种去噪算法)

1.基于小波变换的阈值收缩法去噪 该方法利用小波变换分离出信号中的噪声成分&#xff0c;并通过设置合适的阈值对小波系数进行收缩&#xff0c;保留主要信息的同时&#xff0c;去除噪声。 %基于小波变换的阈值收缩法去噪算法 clear clc Iimread(nana.png); X im2double(I); …

深入理解C语言中的静态库与动态库 —— 原理与实践

引言 在 C 语言编程中&#xff0c;库是预编译的代码集合&#xff0c;用于实现特定功能&#xff0c;以供其他程序使用。库可以分为静态库和动态库两种主要类型。静态库在编译阶段被链接到目标程序中&#xff0c;而动态库则是在运行时被加载。本文旨在深入探讨这两种库的工作原理…

渗透测试-百日筑基—SQL注入篇时间注入绕过HTTP数据编码绕过—下

day8-渗透测试sql注入篇&时间注入&绕过&HTTP数据编码绕过 一、时间注入 SQL注入时间注入&#xff08;也称为延时注入&#xff09;是SQL注入攻击的一种特殊形式&#xff0c;它属于盲注&#xff08;Blind SQL Injection&#xff09;的一种。在盲注中&#xff0c;攻击…

Android 在github网站下载项目:各种很慢怎么办?比如gradle下载慢;访问github慢;依赖下载慢

目录 访问github慢gradle下载慢依赖下载慢 前言 大家好&#xff0c;我是前期后期&#xff0c;在网上冲浪的一名程序员。 为什么要看这篇文章呢&#xff1f;问题是什么&#xff1f; 我们在Github上面看到一些好的项目的时候&#xff0c;想下载下来研究学习一下。但经常遇到各…

外面卖几百的Ai数字人软件 说123456生成视频 去授权版本

下载&#xff1a;https://pan.quark.cn/s/27a0cff98eae 可以无限制使用。

网络拓扑视角下的IP地址管理优化

前言 对IP地址进行有效管理&#xff0c;好处是能 提升网络运行效率&#xff0c;还可以保障网络安全和稳定。网络拓扑结构本身作为网络描述中各节点联系的主要角色&#xff0c;为IP地址管理提供了一些优化策略。 网络拓扑和IP地址管理的关系 网络拓扑结构描述了网络中各节点&a…

【Spring MVC】响应结果和设置

​ 我的主页&#xff1a;2的n次方_ 1. 返回静态页面 先创建一个 html 页面 ​ 如果还按照之前的方式进行返回的话&#xff0c;返回的并不是一个 html 页面 RequestMapping("/response") RestController public class ResponseController {RequestMapping(&quo…

线程同步(互斥锁条件变量)

线程同步 互斥锁(互斥量)条件变量生产/消费者模型 一、互斥锁 C11提供了四种互斥锁&#xff1a; mutex&#xff1a;互斥锁。timed_mutex&#xff1a;带超时机制的互斥锁。recursive_mutex&#xff1a;递归互斥锁。recursive_timed_mutex&#xff1a;带超时机制的递归互斥锁…

命名管道和共享内存

命名管道 管道应用的一个限制就是只能在具有共同祖先的进程间通信&#xff0c;如果我们想在不相关的进程之间交换数据&#xff0c;可以使用FIFO文件来做这项工作&#xff0c;它被称为命名管道&#xff0c;命名管道是一种特殊类型的文件 创建命名管道 int main(int argc, cha…

落地台灯什么牌子好?口碑最好的落地灯品牌

落地台灯什么牌子好&#xff1f;随着落地台灯被越来越多的人认可&#xff0c;如今市场中护眼大路灯品牌类型五花八门&#xff0c;质量存在较大差距。很多网红、明星代言等产品&#xff0c;入行时间短&#xff0c;关注市场营销&#xff0c;而忽视产品核心技术的提升&#xff0c;…

Codeforces Round 982 div2 个人题解(A~D2)

Codeforces Round 982 div2 个人题解(A~D2) Dashboard - Codeforces Round 982 (Div. 2) - Codeforces 火车头 #define _CRT_SECURE_NO_WARNINGS 1#include <algorithm> #include <array> #include <bitset> #include <cmath> #include <cstdio&…

软件系统建设方案书(word参考模板)

1 引言 1.1 编写目的 1.2 项目概述 1.3 名词解释 2 项目背景 3 业务分析 3.1 业务需求 3.2 业务需求分析与解决思路 3.3 数据需求分析【可选】 4 项目建设总体规划【可选】 4.1 系统定位【可选】 4.2 系统建设规划 5 建设目标 5.1 总体目标 5.2 分阶段目标【可选】 5.2.1 业务目…

简记 Vue3(一)—— setup、ref、reactive、toRefs、toRef

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;正逐渐往全干发展 &#x1f4c3;个人状态&#xff1a; 研发工程师&#xff0c;现效力于中国工业软件事业 &#x1f680;人生格言&#xff1a; 积跬步…

API网关的作用--为什么微服务需要一个API网关?

微服务网关核心作用就是协议转换、安全隔离和流量控制 微服务架构中&#xff0c;API网关作为系统的入口点&#xff0c;可以统一处理所有客户端请求。 1&#xff09;协议转换&#xff1a;它能够支持多种通信协议&#xff08;如HTTP、gRPC等&#xff09;之间的相互转换&#xff…

【数据结构】快速排序(三种实现方式)

目录 一、基本思想 二、动图演示&#xff08;hoare版&#xff09; 三、思路分析&#xff08;图文&#xff09; 四、代码实现&#xff08;hoare版&#xff09; 五、易错提醒 六、相遇场景分析 6.1 ❥ 相遇位置一定比key要小的原因 6.2 ❥ 右边为key&#xff0c;左边先走 …

一个关于@JsonIgnore的isxxx()问题

一个关于JsonIgnore的问题 版本:2.13.5 <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><optional>true</optional></dependency>代码&#xff1a; Data public clas…

2024年10月27日历史上的今天大事件早读

公元前628年10月27日 春秋五霸之一晋文公重耳卒 1915年10月27日 美军进入一战前线 1921年10月27日 思想家严复逝世 1927年10月27日 中共创建井冈山根据地 1937年10月27日 八百壮士坚守四行仓库 1937年10月27日 伪“蒙古联盟自治政府”成立 1938年10月27日 日军对中国军队…