该软件是一个本机 C++/MFC 应用程序,它通过 UDP 接收大量数据,然后处理数据以进行显示、声音输出和写入磁盘等操作。我第一次遇到这个问题是从应用程序的帮助菜单启动 CHM 帮助文档,然后在从硬件收集数据时单击帮助文档周围。为了复制这一点,使用 AutoHotkey 脚本在应用程序运行时快速单击帮助文档。一旦系统上出现任何声音,我就开始出现错误。
如果我完全禁用声卡,一切都会正常进行,没有错误,但声音输出显然被禁用。但是,如果我播放声音(在此应用程序中,是不同的应用程序,甚至只是消息框中的蜂鸣声),我会收到数千个丢弃的数据包(我们知道这一点,因为每个数据包都有时间戳)。作为第二个测试,我根本没有使用我的应用程序,只是使用 Wireshark 来监视来自硬件的传入数据包。果然,每当 Windows 中播放声音时,我们都会丢失数据包。事实上,甚至不必主动播放声音也会导致错误。如果我只是创建一个缓冲区(使用 DirectSound8)并且从未开始播放,我仍然会收到这些错误。
这种情况发生在具有多种网卡(光纤和 RJ45)和声卡(集成卡和独立卡)组合的多台 PC 上。我还为每个网卡和声卡尝试了不同的驱动程序版本。所有测试均在 Windows 7 32 位上进行。由于我的应用程序使用 DirectSound 进行音频,因此我尝试了不同的 CooperativeLevels(正常操作是 DSSCL_PRIORITY),但没有成功。
此时,我非常确信它与我的应用程序无关,并且想知道在我开始与硬件供应商和/或 Microsoft 打交道之前是否有人知道可能导致此问题的原因。
The software in question is a native C++/MFC application that receives a large amount of data over UDP and then processes the data for display, sound output, and writing to disk among other things. I first encountered the problem when the application's CHM help document was launched from its help menu and then I clicked around the help document while gathering data from the hardware. To replicate this, an AutoHotkey script was used to rapidly click around in the help document while the application was running. As soon as any sound occurred on the system, I started getting errors.
If I have the sound card completely disabled, everything processes fine with no errors, though sound output is obviously disabled. However, if I have sound playing (in this application, a different application or even just the beep from a message box) I get thousands of dropped packets (we know this because each packet is timestamped). As a second test, I didn't use my application at all and just used Wireshark to monitor incoming packets from the hardware. Sure enough, whenever a sound played in Windows, we had dropped packets. In fact, sound doesn't even have to be actively playing to cause the error. If I simply create a buffer (using DirectSound8) and never start playing, I still get these errors.
This occurs on multiple PCs with multiple combinations of network cards (both fiber optic and RJ45) and sound cards (both integrated and separate cards). I've also tried different driver versions for each NIC and sound card. All tests have been on Windows 7 32bit. Since my application uses DirectSound for audio, I've tried different CooperativeLevels (normal operation is DSSCL_PRIORITY) with no success.
At this point, I'm pretty convinced it has nothing to do with my application and was wondering if anyone had any idea what could be causing this problem before I started dealing with the hardware vendors and/or Microsoft.
发布评论
评论(2)
事实证明,这种行为是设计使然。 Windows Vista 及更高版本实现了称为多媒体类调度程序的东西服务(MMCSS),旨在使所有多媒体播放尽可能流畅。由于多媒体播放依靠硬件中断来保证播放的流畅,任何竞争中断都会导致问题。主要的硬件中断源之一是网络流量。因此,Microsoft 决定在程序在 MMCSS 下运行时限制网络流量。
我想这是一个 大事返回2007 年,当时 Vista 出来了,但我错过了。 Mark Russinovich 发表了一篇文章(感谢 ypnos) 描述 MMCSS。看来我的整个问题可以归结为:
我尚未验证 Windows 7 或 Vista SP1 中是否仍然存在多适配器错误,但如果您遇到问题,则需要查找该错误。
从 Russinovich 帖子的评论中,我发现 Vista SP1 引入了一些注册表设置,允许调整 MMCSS 如何影响 Windows。具体来说是 NetworkThrotdlingIndex 键。
我的问题的解决方案是通过将
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Multimedia\SystemProfile\NetworkThrotdlingIndex
键设置为0xFFFFFFFF
然后重新启动来完全禁用网络限制。这会完全禁用 MMCSS 的网络限制部分。我曾尝试简单地将值提高到70
,但它并没有停止导致错误,直到我完全禁用它。到目前为止,我还没有看到此更改对其他多媒体应用程序(也没有我自己的应用程序的视频捕获和音频输出部分)产生任何不利影响。如果情况发生变化,我会在这里报告。
It turns out that this behavior is by design. Windows Vista and later implemented something called the Multimedia Class Scheduler service (MMCSS) that is intended to make all multimedia playback as smooth as possible. Since multimedia playback relies on hardware interrupts to ensure smooth playback, any competing interrupts will cause problems. One of the major hardware interrupt sources is network traffic. Because of this, Microsoft decided to throttle the network traffic when a program was running under MMCSS.
I guess this was a big deal back in 2007 when Vista came out, but I missed it. There was an article by Mark Russinovich (thanks ypnos) describing MMCSS. It seems that the my entire problem boiled down to this:
I haven't verified that the multiple adapter bug still exists in Windows 7 or Vista SP1, but it is something to look for if you are running into problems.
From the comments on Russinovich's post, I found that Vista SP1 introduced some registry settings that allowed one to adjust how MMCSS affects Windows. Specifically the NetworkThrottlingIndex key.
The solution to my issue was to completely disable network throttling by setting the
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Multimedia\SystemProfile\NetworkThrottlingIndex
key to0xFFFFFFFF
and then rebooting. This completely disables the network throttling portion of MMCSS. I had tried simply upping the value to70
, but it didn't stop causing errors until I completely disabled it.Thus far I have not seen any adverse effects on other multimedia applications (nor the video capture and audio output portions of my own application) from this change. I will report back here if that changes.
众所周知,微软在 Windows Vista 内核中内置了一些奇怪的反功能,这些功能会预防性地降低 I/O 性能,以确保多媒体应用程序(Windows Media Player、directX)获得 100% 的响应能力。我不知道这是否也意味着 UDP 丢包。阅读该方法的蹩脚理由:http://blogs .technet.com/b/markrussinovich/archive/2007/08/27/1833290.aspx
其中一条评论很好地总结了这一点:“在我看来,微软试图‘修复’一些没有损坏的东西”。
It is known that Microsoft built some weird anti-feature into the Windows Vista kernel that will degrade I/O performance preventatively to make sure that multimedia applications (windows media player, directX) get 100% responsiveness. I don't know if that also means packet loss with UDP. Read this lame justification for the method: http://blogs.technet.com/b/markrussinovich/archive/2007/08/27/1833290.aspx
One of the comments there summarizes this quite well: "Seems to me Microsoft tried to 'fix' something that wasn't broken."