Visual Studio 2012拥有丰富的有价值的功能,以至于我听到开发者反馈的需要的新功能新版本已经有了。另外,我听到开发人员询问具体的功能的某个特性,实际上他真正需要的是另外一个功能点。

上面说的两种情况下适用于Visual Studio的.NET内存分配分析器 。 许多开发人员可能会从中受益却不知道它的存在,而另外一些开发者有却对它有不正确的理解。 这样很不好,因为该功能可以提供很多有价值的特定场景; 许多开发在理解的情况下才能发挥其预期的作用。也就是要做到以下两点:第一,知道它的存在,第二,知道如何使用。

为什么内存分析?

当谈到.NET和内存分析,有两个主要的原因之一,可能需要使用一个诊断工具:

1. 发现内存泄漏。

2. 发现不必要的分配。

内存优化的实例

为了更好地理解内存分析器的作用,以及它如何帮助到我们。让我们通过一个示例来理解。

  public static async Task<T> WithCancellation1<T>( this Task<T> task, CancellationToken cancellationToken)
 {
     var tcs = new TaskCompletionSource< bool >();
     using (cancellationToken.Register(() => tcs.TrySetResult( true )))
     if (task != await Task.WhenAny(task, tcs.Task))
         throw new OperationCanceledException(cancellationToken);
     return await task;
 }
上面这段代码的作用是可以异步的取消正在运行的任务
 
  T result = await someTask; 
  T result = await someTask.WithCancellation1(token); 

如果取消要求在任务完成之前,相关的CancellationToken,一个OperationCanceledException将被抛出。

要了解参与这一方法的分配,我们将使用一个小程序去测试。
 
using System;
 using System.Threading;
 using System.Threading.Tasks;
 
 class Harness
 {
     static void Main() 
      { 
          Console.ReadLine(); // wait until profiler attaches
          TestAsync().Wait(); 
      }
     static async Task TestAsync()
     {
         var token = CancellationToken.None;
         for ( int i=0; i<100000; i++)
             await Task.FromResult(42).WithCancellation1(token);
     }
 }
 
 
 static class Extensions
 {
     public static async Task<T> WithCancellation1<T>(
     this Task<T> task, CancellationToken cancellationToken)
     {
         var tcs = new TaskCompletionSource< bool >();
         using (cancellationToken.Register(() => tcs.TrySetResult( true )))
             if (task != await Task.WhenAny(task, tcs.Task))
                 throw new OperationCanceledException(cancellationToken);
         return await task;
     }
 } 

运行.NET内存分配分析器

要启动内存分配分析器,在Visual Studio中去分析菜单并选择“启动性能向导...”。 这将打开如下所示的对话框:

选择“.NET内存分配(取样)”,单击下一步两次,最后是完成。 在这一点上,应用程序将被启动,并剖析将开始监视它的分配(线束上面的代码也需要你按下“Enter”键) 。 当应用程序完成后,或当你手动选择停止剖析,剖析会加载符号,并开始分析跟踪。 这是一个很好的时间去让自己的一杯咖啡,或午​​餐,因为这取决于有多少分配发生后,该工具可以需要一段时间才能做到这一点的分析。

当分析完成后,我们看下报告:

从这里,我们可以进一步研究,通过查看分配汇总(从“当前视图”下拉列表中选择“分配”):

在这里,我们能看到一排的被分配的每种类型,同列显示有多少分配被跟踪的信息,有多少空间与分配,以及如何分配映射回该类型的百分比有关。 我们还可以扩展一个条目看,看到这些分配方法的调用堆栈:

通过选择“功能”的观点,我们可以得到一个不同的支点这一数据,高亮它的功能分配的大多数对象和字节:

剖析分析报告并做相应优化

我们可以分析我们的例子中的结果。 首先,我们可以看到,有相当数量的分配在哪里,这可能是令人惊讶的。毕竟,在我们的例子中我们使用WithCancellation1与已经完成了任务,这意味着应该有很少的工作要做(与已完成的任务,没有什么取消).然而从上面的跟踪我们可以看到,我们的例子中的每一次迭代中产生:

  • 三种分配Task`1的(我们跑了线束10万次,可以看到有〜300K分配)
  • 两个分配task[]

有关任务的辅助业务,它实际上是相当普遍的处理已经完成的任务,因为很多时候,操作执行是异步的,实际上完全同步(例如,在网络流中的一个读操作可以缓冲到内存足够的额外数据来完成后续的读操作)。 因此,优化已经完成的情况下,可以为表现的确有益。 让我们来试试。 这里有一个第二次尝试WithCancellation,一个优化的几个“已完成”的情况:

   public static Task<T> WithCancellation2<T>( this Task<T> task,    CancellationToken cancellationToken)
     {
         if (task.IsCompleted || !cancellationToken.CanBeCanceled)
             return task;
         else if (cancellationToken.IsCancellationRequested)
             return new Task<T>(() => default (T), cancellationToken);
         else
             return task.WithCancellation1(cancellationToken);
     } 

此实现检查:

  • 首先,无论是任务已经完成或是否提供的CancellationToken无法取消; 在两者的那些情况下,有不需要额外的工作,因为取消不能适用,因此我们可以只返回原始任务立即而不是花费任何时间或存储器中创建一个新的。
  • 那么是否取消已要求; 如果有,我们可以分配一个业已取消的任务将返回,而不是花费八个分配我们先前支付给调用我们原来的实现。
  • 最后,如​​果没有这些快速通道申请,我们通过降至调用原始的实现。

再分析我们的微基准,而使用的,而不是WithCancellation1 WithCancellation2提供了大大改善的前景(你很可能会发现,分析的速度远远超过它之前,已经是一个迹象,表明我们已经显著减少内存分配完成)。 现在,我们刚刚有主要业务划分,我们预计,从Task.FromResult一个从线束我们TestAsync方法叫做:

所以,我们现在已经成功了优化,其中任务已经完成,取消在那里不能要求,或者取消已申请的情况。 怎么样的情况下,我们确实需要调用更复杂的逻辑? 是否有可有什么改进?

让我们改变我们的基准来使用,这不是已经由我们引用WithCancellation2,并且还使用可以有取消请求令牌的时间内完成的任务。 这将确保我们使它的“慢”的路径:

       using (cancellationToken.Register(() => tcs.TrySetResult( true ))) 

剖析再次提供了更深入的了解:

在这种缓慢的道路,现在有14%的迭代拨款总额,包括2从我们TestAsync线束(该TaskCompletionSource <int>的我们明确地创建和任务<int>的它创建)。 在这一点上,我们可以使用所有的分析结果提供的信息,了解那里的其余12分配的来源,并随后解决这些问题的是相关的和可能的。 例如,让我们看两个分配具体为:在<> c__DisplayClass2`1实例,这两个动作实例之一。 这两种分配将可能是合乎逻辑的任何人都熟悉的C#编译器如何处理倒闭 。 为什么我们有一个封闭? 由于该行的:

使用(cancellationToken.Register(()=> tcs.TrySetResult( 真 )))

电话注册,是关在'TCS'变量。 但是,这不是严格必需的:该注册方法具有另一个超载,而不是采取一个动作这需要一个Action <object>和该对象的状态被传递给它。 如果我们不是重写此行使用基于状态的过载,以及一个手动缓存的委托,我们能够避免倒闭和这两个分配:

  private static readonly Action< object > s_cancellationRegistration =
     s => ((TaskCompletionSource< bool >)s).TrySetResult( true );
 using (cancellationToken.Register(s_cancellationRegistration, tcs))

重新运行探查证实这两个分配不再发生:

从今天开始分析!

分析,发现和消除热点,然后将再次围绕这个周期是改善代码的性能,常见的方法是否使用CPU分析器和内存分析器。 所以,如果你发现内存分配有可能程序的瓶颈,不妨尝试.NET的内存分配分析器。

转载于:https://www.cnblogs.com/sennly/p/4179418.html

Visual Studio的.NET内存分配分析器解析相关推荐

  1. ART对象内存分配过程解析(上)——内存分配的准备阶段(Android 8.1)

    注:本文基于Android 8.1进行分析. ART对象分配过程解析--内存分配的准备阶段 本章我们将分析Android 8.1中ART虚拟机的对象创建时内存分配过程的分析.本节将介绍内存分配相关的环 ...

  2. Visual Studio中检测内存泄漏的方法(一)

    有些内存泄露是不会dump出来详细信息的,只会给出内存块号,这种情况一下一般可以用一下方法调试出来. 这两天调一个程序,发现每次退出都有内存泄漏,在此总结一个调试内存泄漏的好方法. 对于比较明显的内存 ...

  3. 使用 Visual Studio 分析器找出应用程序瓶颈(转)

    使用 Visual Studio 分析器找出应用程序瓶颈 Hari Pulapaka and Boris Vidolov 本文讨论: 以性能瓶颈为目标 应用程序代码分析 比较分析数据 性能报告 本文使 ...

  4. Visual Studio 2017 RC 下载 最新版本的发行说明

    我们非常荣幸地宣布 Visual Studio 2017 RC 现已推出! 此新版本包括我们最新的功能创新和改进. 注意 这里是 Visual Studio 2017 最新版本的发行说明. 下载:Vi ...

  5. Visual Studio 2017 新功能(上)

    开发:快速导航.编写并修复代码 新的安装体验 - 降低了最小内存需求量以实现更快.更定制化的安装,并且支持脱机安装. Visual Studio IDE - 大幅改进了 Visual Studio 2 ...

  6. Visual Studio 2005 中的新增安全性功能

    Visual Studio 2005 中的新增安全性功能 Visual Studio 2005 中的新增安全性功能 发布日期: 11/18/2005 | 更新日期: 11/18/2005 Brian ...

  7. [Visual Studio+TFS--强大的项目管理工具]

    [Visual Studio+TFS–强大的项目管理工具] 一.前言 微软的Visual Studio非常强大,可以无缝结合Git或自家的TFS(Team Foundation Server),进行项 ...

  8. 【更新】ReSharper v2016.3发布,Visual Studio 2017 RC初步支持

    2019独角兽企业重金招聘Python工程师标准>>> [下载最新版ReSharper试用] Visual Studio 2017 RC初步支持 ReSharper 2016.3最终 ...

  9. 等待十年,史上第一个 64 位版 Visual Studio 将于今夏公开首个预览版!

    昨日,微软在其开发者博客宣布了一则重磅消息--Visual Studio 2022 首个预览版将于今年夏季发布 ,并且终于成为万众期待的 64 位版! 要知道,早在 2011 年就有用户在 Visua ...

最新文章

  1. 通俗讲解从Transformer到BERT模型!
  2. 性价比高出英特尔45%,亚马逊的云服务器芯片如何做到?| 解读
  3. BZOJ 1049 数字序列(LIS)
  4. java 文件流关闭 finally,关于java:为什么需要在“ finally”内关闭文件,而仍将其嵌入在“ try / catch”块内?...
  5. C语言指定编译对齐方式
  6. linux怎么修改bash,Linux操作系统中如何对Bash变量内容修改?
  7. Celery增加Systemd配置
  8. 编译安装nginx并修改版本头信息—参考实例
  9. BZOJ3669[NOI2014] 魔法森林
  10. bert模型使用记录
  11. 转:飞思卡尔单片机RAM与flash相关问题
  12. 软件工程本科生实习_我从n00b实习生到工程团队主管的方式
  13. 如何用Python写一个上课点名系统
  14. 华硕路由桥接模式进入不了界面
  15. 计算机二级和公共英语三级考试时间,英语三级考试时间,全国英语等级考试三级时间。...
  16. 揭秘:一线互联网薪资曝光,看看你的价值,有没有被低估?
  17. GIC spec之ITS和LPI中断2
  18. 把电脑端的图片链接转换为API接口可以调用的链接
  19. android fake gps,Fake GPS Location
  20. mysql操作窗口如何设置粘贴_现在我在学习MySQL,问问怎么复制粘贴数据库

热门文章

  1. mybatis list为入参_Mybatis进阶学习
  2. python变量的作用_Python中的变量
  3. c语言注释符的作用有哪两种,C语言编程的注释符号是?
  4. html宽度满屏,宽度满屏的代码怎么样写?
  5. java ip解析_java域名解析
  6. python中的模块_python3.0中重载模块
  7. 达而稳 驱动 fl2000dx_Intel-AMD核显驱动没人管:Win10无法升级,不要撞车
  8. osea/ Overview 概述
  9. RabbitMQ教程_4 Java 使用rabbitmq
  10. Kubernetes 1.14.1快速升级