我正在尝试找出未充分利用 CPU 的 C# 服务器应用程序的瓶颈所在。我认为这可能是由于磁盘 I/O 性能不佳造成的,与应用程序本身无关,但我无法从这个假设中得出事实。
应用程序从本地 MSMQ 队列读取消息,对每条消息进行一些处理,并在处理完消息后,将响应消息发送到另一个本地 MSMQ 队列。
我正在使用异步循环从队列中读取消息,尽可能快地将它们从队列中取出并使用 Task.Run 调度它们进行处理以启动每个消息的处理(并且不要在此 Task.Run 上等待 .. 只是附加一个延续只会在它上面出错以记录错误)。每条消息都是并发处理的,即无需等待消息完全处理后再处理下一条消息。
在消息处理结束时,我正在使用 MessageQueue 的 Send 方法(不知何故异步但不是真的,因为它必须在返回之前等待磁盘写入 - 请参阅 System.Messaging - why MessageQueue does not offer an asynchronous version of Send)。
对于基准测试,我在队列中排队 100K 条消息(100K 条消息的总大小约为 100MB),然后启动程序。在我的两台个人电脑上(一台是 SSD HD,另一台是 SATA2 HD,配备 i7 CPU 四核 -8 逻辑进程 -)我在程序生命周期内达到约 95% 的 CPU 使用率(出列 100K 消息,处理它们并发送回复)。消息尽可能快地出队,尽可能快地处理(此处涉及 CPU),然后响应发送到不同本地队列的每条消息。
现在在运行非 HT 双核 CPU 的虚拟机上(不知道底层磁盘是什么,但性能似乎远低于我的......在基准测试期间,使用 Perfmon 我可以看到平均磁盘秒/写大约 10-15 ms 在这个 VM 上,而在我的个人机器上大约是 2ms)当我运行同一个工作台时,我只达到 ~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 . 您应该从 Windows 8.1 SDK(需要 .NET 4.5.1)中获取最新版本,它为您提供了大部分功能,但来自 Windows 8 SDK 的版本也不错。
您可以在此处获得图表 % CPU 利用率和 % 磁盘利用率。如果其中一个为 100% 而另一个为低,那么您就找到了瓶颈。由于它是一个系统范围的分析器,您可以检查 msmq 服务是否在错误地使用光盘或您或其他人(例如,病毒扫描程序是一个常见问题)。
您可以直接访问您的调用堆栈并检查哪个进程和线程确实唤醒了您的工作线程,它应该全速运行。然后你可以跳转到准备线程并处理并检查它在准备你的线程之前做了什么。这样你就可以直接验证是什么阻碍了它这么久。
不用再猜了。您可以真正看到系统在做什么。
要在 CPU Usage Precise 中进一步分析,请查看以下列:
然后向下钻取您进程中的调用堆栈,以查看本应全速运行的线程中发生高等待 (us) 时间的位置。您可以向下钻取到一个事件,直到您可以不进一步。然后您将在 Readying Process 和 ReadyingThreadId 中看到值。转到那个进程/线程(它可以是你自己的)并重复这个过程,直到你结束一些涉及磁盘 IO 或 sleep 或长时间运行的设备驱动程序调用(例如病毒扫描程序或 vm 驱动程序)的阻塞操作。
关于c# - CPU 未充分利用。由于阻塞 I/O?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19748129/
我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL
我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
我刚刚安装了带有RVM的Ruby2.2.0,并尝试使用它得到了这个:$rvmuse2.2.0--defaultUsing/Users/brandon/.rvm/gems/ruby-2.2.0dyld:Librarynotloaded:/usr/local/lib/libgmp.10.dylibReferencedfrom:/Users/brandon/.rvm/rubies/ruby-2.2.0/bin/rubyReason:Incompatiblelibraryversion:rubyrequiresversion13.0.0orlater,butlibgmp.10.dylibpro
我如何做Ruby方法"Flatten"RubyMethod在C#中。此方法将锯齿状数组展平为一维数组。例如:s=[1,2,3]#=>[1,2,3]t=[4,5,6,[7,8]]#=>[4,5,6,[7,8]]a=[s,t,9,10]#=>[[1,2,3],[4,5,6,[7,8]],9,10]a.flatten#=>[1,2,3,4,5,6,7,8,9,10 最佳答案 递归解决方案:IEnumerableFlatten(IEnumerablearray){foreach(variteminarray){if(itemisIEnume
我最近从C#转向了Ruby,我发现自己无法制作可折叠的标记代码区域。我只是想到做这种事情应该没问题:classExamplebegin#agroupofmethodsdefmethod1..enddefmethod2..endenddefmethod3..endend...但是这样做真的可以吗?method1和method2最终与method3是同一种东西吗?还是有一些我还没有见过的用于执行此操作的Ruby惯用语? 最佳答案 正如其他人所说,这不会改变方法定义。但是,如果要标记方法组,为什么不使用Ruby语义来标记它们呢?您可以使用
什么是Linq聚合方法的ruby等价物。它的工作原理是这样的varfactorial=new[]{1,2,3,4,5}.Aggregate((acc,i)=>acc*i);每次将数组序列中的值传递给lambda时,变量acc都会累积。 最佳答案 这在数学以及几乎所有编程语言中通常称为折叠。它是更普遍的变形概念的一个实例。Ruby从Smalltalk中继承了这个特性的名称,它被称为inject:into:(像aCollectioninject:aStartValueinto:aBlock一样使用。)所以,在Ruby中,它称为inj
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭8年前。Improvethisquestion几年前我去学校学习编程,毕业后我找到了一份系统管理方面的工作,这就是我职业生涯的方向。我想重新开始某种开发,并且一直在“玩”C#和ASP.NET,但我已经听到很多关于其他"new"语言的讨论(新的意思是它们是新的)我)喜欢Ruby和F#。我想我想知道我是否在浪费时间学习主要的MS语言,而不是成为一名通才。很长一段时间没有离开开发社区(如果我曾经离开过的话)让我在潮流中挣扎,我不想落在时代的
我有一个简单的Ruby脚本,我用它在某些HTTPheader上执行private_encrypt以签署要发送到rubyRESTAPI的Web请求,该API会根据Base64编码字符串测试Base64编码字符串生成而不是解码Base64和解密数据然后测试原始字符串。我使用的脚本是require"openssl"require"base64"path_to_cert=ARGV[0].dupplain_text=Base64.decode64(ARGV[1].dup)private_key=OpenSSL::PKey::RSA.new(File.read(path_to_cert))pu