使用分析工具降低计算成本 您所在的位置:网站首页 彻底删除idea插件缓存 使用分析工具降低计算成本

使用分析工具降低计算成本

2023-05-30 13:13| 来源: 网络整理| 查看: 265

使用分析工具降低计算成本来优化代码(C#、Visual Basic、C++、F#) 项目 05/29/2023

适用范围:Visual Studio Visual Studio for Mac Visual Studio Code

缩短计算时间意味着降低成本,因此优化代码可以节省资金。 CPU 使用率工具可帮助你捕获和可视化应用程序中使用计算资源的位置。 CPU 使用率视图(如调用树和火焰图)提供了一个良好的图形可视化效果,其中显示了应用程序中所用时间的分布情况。 此外,自动见解可能会显示产生很大影响的精确优化。 其他分析工具还可用于提供有关应用性能所发生情况的其他见解。

开始调查 若要降低计算成本,请通过跟踪 CPU 使用率开始调查。 CPU 使用率工具通常有助于开始性能调查并优化代码以降低成本。 如果需要其他见解来帮助隔离问题或提高性能,请考虑使用其他分析工具之一收集跟踪。 例如: 查看内存使用情况。 对于 .NET,请先尝试 .NET 对象分配工具。 对于 .NET 或 C++,可以查看内存使用情况工具。 如果应用使用文件 I/O,请使用文件 I/O 工具。 如果使用的是 ADO.NET 或 Entity Framework,可以尝试使用数据库工具来检查 SQL 查询、精确查询时间等。 有关比较工具,请参阅应选择哪种工具? 示例

本文中显示的示例屏幕截图基于 .NET 应用,该应用针对博客和关联的博客文章的数据库运行查询。 首先检查 CPU 使用率跟踪,以寻找优化和降低计算成本的机会。 大致了解所发生的情况后,还将查看其他分析工具的跟踪,以帮助隔离问题。

若要收集本文中显示的数据,请执行以下操作:

将应用设置为发布版本 从性能探查器 (Alt+F2) 中选择 CPU 使用率工具。 (后面的步骤涉及一些其他工具。) 在性能探查器中,启动应用并收集跟踪。 检查高 CPU 使用率的区域

首先使用 CPU 使用率工具收集跟踪。 加载诊断数据时,首先检查显示热门见解和热路径的初始 .diagsession 报表页。 热路径显示应用中 CPU 使用率最高的代码路径。 这些部分可能会提供提示,帮助你快速识别可以改进的性能问题。

还可以在“调用树”视图中查看热路径。 若要打开此视图,请使用报表中的“打开详细信息”链接,然后选择“调用树”。

在此视图中,你将再次看到热路径,其中显示了应用中 GetBlogTitleX 方法的高 CPU 使用率,占应用 CPU 使用率的 60% 左右。 对 LINQ DLL 的两次外部调用使用大部分 CPU 时间。 这是你可能想要查找 LINQ 查询作为要优化的领域的第一个线索。

若要获取可视化的调用树和不同的数据视图,请切换到“火焰图”视图(从与“调用树”相同的列表中选择)。 同样,GetBlogTitleX 方法似乎对应用的大量 CPU 使用率负责(黄色所示)。 对 LINQ DLL 的外部调用显示在 GetBlogTitleX 框下方,它们使用方法的所有 CPU 时间。

收集其他数据

如果 CPU 使用率工具未提供足够的信息来隔离问题,或者你需要其他见解来帮助提高性能,则可以决定使用其他分析工具之一。 例如,由于我们标识了 LINQ DLL,因此我们将首先尝试数据库工具。 可以多重选择此工具以及 CPU 使用率。 收集跟踪后,选择“诊断”页中的“查询”选项卡。

在数据库跟踪的“查询”选项卡中,可以看到第一行显示最长的查询,即 2446 毫秒。 “记录”列显示查询读取的记录数。 我们可以使用此信息进行以后的比较。

通过检查 LINQ 在“查询”列中生成的 SELECT 语句,可以将第一行标识为与 GetBlogTitleX 方法关联的查询。 “查询”列中的完整查询字符串为:

SELECT "b"."Url", "b"."BlogId", "p"."PostId", "p"."Author", "p"."BlogId", "p"."Content", "p"."Date", "p"."MetaData", "p"."Title" FROM "Blogs" AS "b" LEFT JOIN "Posts" AS "p" ON "b"."BlogId" = "p"."BlogId" ORDER BY "b"."BlogId"

若要查看应用的内存使用情况,请使用 .NET 对象分配工具收集跟踪。 内存跟踪中的“调用树”视图显示热路径,有助于识别高内存使用率的区域。 毫不奇怪,GetBlogTitleX 方法似乎正在生成大量对象! 事实上,超过 900,000 个对象分配。

创建的大多数对象是字符串、对象数组和 Int32。 可以通过检查源代码来查看这些类型的生成方式。

优化代码

是时候查看 GetBlogTitleX 源代码了。 在 .NET 对象分配工具中,右键单击方法,然后选择“转到源文件”。 在 GetBlogTitleX 的源代码中,我们发现以下代码使用 LINQ 读取数据库。

foreach (var blog in db.Blogs.Select(b => new { b.Url, b.Posts }).ToList()) { foreach (var post in blog.Posts) { if (post.Author == "Fred Smith") { Console.WriteLine($"Post: {post.Title}"); } } }

此代码使用 foreach 循环在数据库中搜索以“Fred Smith”为作者的任何博客。 查看该博客,可以看到内存中生成了大量对象:数据库中每个博客的新对象数组、每个 URL 的关联字符串以及文章中包含的属性的值(如博客 ID)。

请进行一些研究,找到有关如何优化 LINQ 查询的一些常见建议,并生成此代码。

foreach (var x in db.Posts.Where(p => p.Author.Contains("Fred Smith")).Select(b => b.Title).ToList()) { Console.WriteLine("Post: " + x); }

在此代码中,你进行了一些更改以帮助优化查询:

添加 Where 子句并消除其中一个 foreach 循环。 仅投影标题属性,该属性是此示例中所需的所有内容。

接下来,使用分析工具重新测试。

检查结果

更新代码后,重新运行 CPU 使用率工具以收集跟踪。 “调用树”视图显示 GetBlogTitleX 仅运行了 1754 毫秒,占用应用的 CPU 总数的 37%,比 59% 有了显著改善。

切换到“火焰图”视图以查看改进的另一个可视化效果。 在此视图中,GetBlogTitleX 也使用 CPU 的较小部分。

检查数据库工具跟踪中的结果,使用此查询仅读取两条记录,而不是 100,000 条! 此外,查询得到了大大简化,并消除了之前生成的不必要的 LEFT JOIN。

接下来,在 .NET 对象分配工具中重新检查结果,查看 GetBlogTitleX 仅负责 56,000 个对象分配,比 900,000 减少近 95%!

迭代

可能需要多次优化,可以继续循环访问代码更改,以查看哪些更改可提高性能并降低计算成本。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有