CPU 未充分利用。由于阻塞 I/O?

2023-12-20

我试图找到未充分利用 CPU 的 C# 服务器应用程序的瓶颈所在。我认为这可能是由于磁盘 I/O 性能不佳造成的,与应用程序本身无关,但我很难从这个假设中得出事实。

应用程序从本地 MSMQ 队列读取消息,对每条消息进行一些处理,并在处理消息后将响应消息发送到另一个本地 MSMQ 队列。

我正在使用异步循环从队列中读取消息,尽快将它们出队,并使用 Task.Run 调度它们进行处理,以启动每个消息的处理(并且不要等待此 Task.Run .. 只是附加一个延续仅对其进行故障记录错误)。每条消息都是并发处理的,即无需等待一条消息完全处理后再处理下一条消息。

在消息处理结束时,我使用 MessageQueue 的 Send 方法(某种程度上是异步的,但实际上并非如此,因为它必须在返回之前等待磁盘写入 -参见System.Messaging - 为什么 MessageQueue 不提供 Send 的异步版本 https://stackoverflow.com/questions/19746992/system-messaging-why-messagequeue-does-not-offer-an-asynchronous-version-of-se-).

对于基准测试,我将 100K 消息放入队列中(100K 消息的总大小约为 100MB),然后启动该程序。在我的两台个人计算机上(一台是 SSD HD,另一台是 SATA2 HD,具有 i7 CPU 四核 -8 个逻辑进程 -),在程序生命周期期间,我的 CPU 使用率达到了约 95%(使 100K 消息出队、处理它们并发送回复)。消息尽可能快地出队、尽可能快地处理(这里涉及 CPU),然后对发送到不同本地队列的每条消息进行响应。

现在在运行非 HT 双核 CPU 的虚拟机上(不知道底层磁盘是什么,但似乎性能远不如我的磁盘...在基准测试期间,使用 Perfmon 我可以看到平均磁盘秒/写入时间约为 10-15 毫秒VM,而在我的个人计算机上约为 2 毫秒)当我运行相同的工作台时,我仅达到 ~55% CPU(当我在计算机上运行相同的工作台而不向队列发送响应消息时,我达到 ~90% CPU) )。

我真的不明白这里有什么问题。似乎很明显,向队列发送消息是问题所在,并且会减慢程序的全局处理速度(以及要处理的消息的出队),但为什么要考虑到我正在使用 Task.Run 启动每个出队消息的处理并最终发送响应,我不希望 CPU 得到充分利用。除非一个线程发送消息时,它会在等待返回(磁盘写入)时阻止其他线程在同一核心上运行,在这种情况下,考虑到延迟比我的个人计算机上高得多,这可能是有意义的,但一个线程等待 I/O 不应阻止其他线程的运行。

我真的很想理解为什么我在这台机器上没有达到至少 95% 的 cpu 使用率。我盲目地说这是由于磁盘 I/O 性能较差,但考虑到我正在使用 Task.Run 同时运行处理,我仍然不明白为什么它会导致 CPU 利用率不足。这也可能是一些与磁盘完全无关的系统问题,但考虑到 MessageQueue.Send 似乎是问题所在,并且该方法最终将消息写入内存映射文件+磁盘,我不知道性能问题可能来自哪里除了磁盘之外。

当然,这肯定是一个系统性能问题,因为程序在我自己的计算机上最大化了 CPU 使用率,但我需要找到 VM 系统上的瓶颈到底是什么,以及为什么它会影响我的应用程序的并发/速度。

任何想法 ?


要检查磁盘和/或 CPU 利用率不佳,只有一种工具:Windows Performance Toolkit。有关如何使用它的示例,请参阅here http://geekswithblogs.net/akraus1/archive/2012/12/19/151604.aspx。 您应该从 Windows 8.1 SDK 获取最新版本(需要 .NET 4.5.1),它为您提供大部分功能,但 Windows 8 SDK 也可以。

您可以在此处获得 CPU 利用率百分比和磁盘利用率百分比图表。如果其中一个为 100%,而另一个则较低,那么您就找到了瓶颈。由于它是一个系统范围的分析器,您可以检查 msmq 服务是否严重使用光盘,或者您或其他人(例如,病毒扫描程序是一个常见问题)。

您可以直接访问调用堆栈并检查哪个进程和线程唤醒了应该全速运行的工作线程。然后,您可以跳转到准备线程并进行处理并检查它在准备线程之前做了什么。这样你就可以直接验证是什么阻碍了它这么久。

不用再猜测了。您可以真正看到系统在做什么。

要进一步分析,请在 CPU 使用率精确视图中启用以下列:

  • 新流程
  • 新线程ID
  • NewThreadStack(框架标签)
  • 准备过程
  • 准备线程ID
  • 准备(我们)总和
  • 等待(我们) 总和
  • Wait(us)
  • %CPU使用率

然后向下钻取进程中的调用堆栈,以查看在应该全速运行的线程中哪些地方确实出现了较长的等待时间。您可以向下钻取到一个事件,直到无法再进一步为止。然后您将看到 Readying Process 和 ReadyingThreadId 中的值。转到该进程/线程(可以是您自己的)并重复该过程,直到您最终陷入某些阻塞操作,该操作涉及磁盘 IO 或睡眠或长时间运行的设备驱动程序调用(例如病毒扫描程序或虚拟机驱动程序)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CPU 未充分利用。由于阻塞 I/O? 的相关文章

  • 在 LINQ 查询中返回不带时间的日期

    我正在编写一个查询 我想计算按日期联系我们的呼叫中心的次数 看起来很简单 但由于联系日期字段是日期时间字段 我得到了时间 因此当我按联系日期 时间 分组时 每个联系日期实例的计数为 1 所以 我想只按日期分组 而不按时间分组 下面是我用来查
  • 创建 DirectoryEntry 实例以供测试使用

    我正在尝试创建 DirectoryEntry 的实例 以便可以使用它来测试将传递 DirectoryEntry 的一些代码 然而 尽管进行了很多尝试 我还是找不到实例化 DE 并初始化它的 PropertyCollection 的方法 我有
  • 如何在 Unity 中从 RenderTexture 访问原始数据

    问题的简短版本 我正在尝试访问 Unity 中 RenderTexture 的内容 我一直在使用 Graphics Blit 使用自己的材质进行绘制 Graphics Blit null renderTexture material 我的材
  • 为什么 ConcurrentHashMap::putIfAbsent 比 ConcurrentHashMap::computeIfAbsent 更快?

    使用 ConcurrentHashMap 我发现computeIfAbsent 比putIfAbsent 慢两倍 这是简单的测试 import java util ArrayList import java util List import
  • C# 中可空类型是什么?

    当我们必须使用nullable输入 C net 任何人都可以举例说明 可空类型 何时使用可空类型 https web archive org web http broadcast oreilly com 2010 11 understand
  • 如何在 WPF RichTextBox 中跟踪 TextPointer?

    我正在尝试了解 WPF RichTextBox 中的 TextPointer 类 我希望能够跟踪它们 以便我可以将信息与文本中的区域相关联 我目前正在使用一个非常简单的示例来尝试弄清楚发生了什么 在 PreviewKeyDown 事件中 我
  • 使用 C# 在 WinRT 中获取可用磁盘空间

    DllImport kernel32 dll SetLastError true static extern bool GetDiskFreeSpaceEx string lpDirectoryName out ulong lpFreeBy
  • HttpClient 像浏览器一样请求

    当我通过 HttpClient 类调用网站 www livescore com 时 我总是收到错误 500 可能服务器阻止了来自 HttpClient 的请求 1 还有其他方法可以从网页获取html吗 2 如何设置标题来获取html内容 当
  • 按字典顺序对整数数组进行排序 C++

    我想按字典顺序对一个大整数数组 例如 100 万个元素 进行排序 Example input 100 21 22 99 1 927 sorted 1 100 21 22 927 99 我用最简单的方法做到了 将所有数字转换为字符串 非常昂贵
  • A* 之间的差异 pA = 新 A;和 A* pA = 新 A();

    在 C 中 以下两个动态对象创建之间的确切区别是什么 A pA new A A pA new A 我做了一些测试 但似乎在这两种情况下 都调用了默认构造函数 并且仅调用了它 我正在寻找性能方面的任何差异 Thanks If A是 POD 类
  • 是否有比 lex/flex 更好(更现代)的工具来生成 C++ 分词器?

    我最近将源文件解析添加到现有工具中 该工具从复杂的命令行参数生成输出文件 命令行参数变得如此复杂 以至于我们开始允许它们作为一个文件提供 该文件被解析为一个非常大的命令行 但语法仍然很尴尬 因此我添加了使用更合理的语法解析源文件的功能 我使
  • 像“1$”这样的位置参数如何与 printf() 一起使用?

    By man I find printf d width num and printf 2 1 d width num 是等价的 但在我看来 第二种风格应该与以下相同 printf d num width 然而通过测试似乎man是对的 为什
  • 网络参考共享类

    我用 Java 编写了一些 SOAP Web 服务 在 JBoss 5 1 上运行 其中两个共享一个类 AddressTO Web 服务在我的 ApplycationServer 上正确部署 一切都很顺利 直到我尝试在我的 C 客户端中使用
  • 检查 url 是否指向文件或页面

    我们需要以下内容 如果文件确实是文件 则从 URL 下载该文件 否则 如果它是一个页面 则什么也不做 举个简单的例子 我有以下命令来下载文件 My Computer Network DownloadFile http www wired c
  • 已过时 - OpenCV 的错误模式

    我正在使用 OpenCV 1 进行一些图像处理 并且对 cvSetErrMode 函数 它是 CxCore 的一部分 感到困惑 OpenCV 具有三种错误模式 叶 调用错误处理程序后 程序终止 Parent 程序没有终止 但错误处理程序被调
  • 如何在内存中存储分子?

    我想将分子存储在内存中 这些可以是简单的分子 Methane CH4 C H bond length 108 7 pm H H angle 109 degrees But also more complex molecules like p
  • ListDictionary 类是否有通用替代方案?

    我正在查看一些示例代码 其中他们使用了ListDictionary对象来存储少量数据 大约 5 10 个对象左右 但这个数字可能会随着时间的推移而改变 我使用此类的唯一问题是 与我所做的其他所有事情不同 它不是通用的 这意味着 如果我在这里
  • GDK3/GTK3窗口更新的精确定时

    我有一个使用 GTK 用 C 语言编写的应用程序 尽管该语言对于这个问题可能并不重要 这个应用程序有全屏gtk window与单个gtk drawing area 对于绘图区域 我已经通过注册了一个刻度回调gtk widget add ti
  • 将 viewbag 从操作控制器传递到部分视图

    我有一个带有部分视图的 mvc 视图 控制器中有一个 ActionResult 方法 它将返回 PartialView 因此 我需要将 ViewBag 数据从 ActionResult 方法传递到 Partial View 这是我的控制器
  • 不同类型的指针可以互相分配吗?

    考虑到 T1 p1 T2 p2 我们可以将 p1 分配给 p2 或反之亦然吗 如果是这样 是否可以不使用强制转换来完成 或者我们必须使用强制转换 首先 让我们考虑不进行强制转换的分配 C 2018 6 5 16 1 1 列出了简单赋值的约束

随机推荐

  • 检测 Google Chrome 页面预取

    我正在构建一个简单的工具来跟踪和增加网站的访问次数 这很简单 当服务器收到 GET 请求时 它会将数据库中该网站的计数器加 1 但是 我在使用 Google Chrome 的预渲染引擎时遇到了一些问题 预测网络操作以提高页面加载性能 该网站
  • 将模板与 HTML 自定义元素结合使用

    我刚刚开始学习 HTML 自定义元素 通过阅读一系列介绍 教程和文档 我想我已经很好地掌握了它的工作原理 但我对正确使用或不使用的方法有一个哲学问题这
  • MVC 4 中的部分实体类未显示数据注释

    我已经看到了许多关于如何通过部分类向通过实体框架生成的类添加元数据注释的解释 数据库优先 有人可以告诉我为什么这些新的显示值没有显示在我的视图中吗 这两个都是与我的实体框架生成的类相同的命名空间的一部分 MetadataType typeo
  • 为什么 pip 在我的虚拟环境之外安装软件包?

    在做了虚拟环境的来源之后我尝试 pip install U no deps django social auth 它返回 OSError Errno 13 Permission denied usr local lib python2 6
  • 如何确保 Angular 服务构造函数中的异步初始化完成?

    请专家告诉我 在调用类中的其他函数时 如何确保服务构造函数中的异步初始化完成 constructor var sock new SockJS this chatUrl this stompClient Stomp over sock thi
  • NASM - 如何创建结构指针数组并访问它们

    所以我的问题是这样的 我有一个名为顶点的结构 struc vertex x resq 1 y resq 1 z resq 1 endstruc 我想创建一个指向由该定义组成的结构的指针数组 就像加载顶点表单文件并将它们保存在结构中和数组中的
  • 将图像从 URL 上传到 Firebase 存储

    我想知道如何通过 URL 而不是输入 例如 将文件上传到 Firebase 的存储中 我正在从网站上抓取图像并检索它们的 URL 我想通过 foreach 语句传递这些 URL 并将它们上传到 Firebase 的存储 现在 我有 fire
  • RXJS 拖放

    这个问题与 RXJS 有关 我正在尝试调整 github 中的拖放示例以适用于一类 div 而不仅仅是单个元素 ID https github com Reactive Extensions RxJS blob master example
  • 标记实例变量@private

    我注意到苹果的很多界面都使用 private在它们的实例变量声明之前 这有什么好的设计理由吗 我应该这样做吗 私有实例变量用于将接口与实现分开 在 Objective C 中 由于类声明must显示所有实例变量 需要有一种方法来防止子类访问
  • 实体框架中 IMigrationMetadata 接口的用途和语义

    我试图找出 EF 中 System Data Entity Migrations Infrastruct IMigrationMetadata 接口的语义是什么 我知道它用于管理和应用数据库迁移 但我找不到有关它的详细信息 具体来说我想知道
  • 安卓键盘记录器

    我正在为 Android 编写一个用于考试的应用程序 该应用程序的功能之一是键盘记录器 它可以捕获用户键入的所有内容 我不明白如何实现键盘记录器的功能 如果有可能捕获用户输入的所有内容 不幸的是我在网络中发现了很少的代码 谁能帮我 感谢您的
  • 如何在 QML 中的 ListView 中绑定到来自委托组件的信号

    假设我有一个ListView可点击的委托组件 或GridView or Repeater 这些委托组件需要在触发时发出信号以及自定义数据 该信号可以由父组件拾取ListView 如何实现这种信号结合 例如以下代码是我的尝试 但我不知道如何绑
  • Unity 5.1 动画控制器不转换

    我创建了一个Animator Controller 称为Player 并将其分配给Animator我的人形化身的领域 以及具有适当过渡的简单动画状态 请参阅所附的两张图片 我已将包含以下代码的脚本附加到我的头像游戏对象 但我想知道我遗漏了什
  • 跨子域使用localStorage

    我将 cookie 替换为本地存储 http www smashingmagazine com 2010 10 11 local storage and how to use it 在可以支持它的浏览器上 除了 IE 之外的任何浏览器 问题
  • 如何从一个 Visual Studio 项目创建两个不同的可执行文件

    我有一个主要可执行文件 它根据配置文件中保存的设置运行 我希望能够通过不同的可执行文件更改配置文件中的设置 有没有一种简单的方法可以在一个 Windows 窗体项目中构建这两个不同的可执行文件 这意味着当我按构建时 会在同一解决方案文件夹中
  • 阶乘法导致错误

    我正在尝试获取数字的阶乘值66 但是我的方法给了我一个输出0 但每当我尝试获取阶乘5 这给我带来了输出120 谁能告诉我为什么吗 public static int factorial int n if n 1 return n retur
  • 如何在 Python 中随机分布 N 个质量,使它们遵循 Plummer 密度分布

    我正在用Python工作 我有N恒星 每一颗都有一个太阳质量M 0 我想将这些星星随机分布在一定半径的体积中R 使得密度分布遵循普鲁默模型 http en wikipedia org wiki Plummer model 由以下公式给出 我
  • 使用 databricks-connect 时打开 dbfs 上的文件

    我正在使用 databricks connect 将本地 PyCharm IDE 连接到 Azure Databricks 群集 在我尝试在没有 Spark 上下文的情况下访问文件之前 这一切都工作得很好 例如 dbutils fs put
  • 如何将 io.Reader 转换为 io.ReadCloser? [复制]

    这个问题在这里已经有答案了 我有一个io Reader不需要关闭 stringReader strings NewReader shiny 我想将它传递给接收的方法io ReadCloser func readAndClose source
  • CPU 未充分利用。由于阻塞 I/O?

    我试图找到未充分利用 CPU 的 C 服务器应用程序的瓶颈所在 我认为这可能是由于磁盘 I O 性能不佳造成的 与应用程序本身无关 但我很难从这个假设中得出事实 应用程序从本地 MSMQ 队列读取消息 对每条消息进行一些处理 并在处理消息后