Windows 7:下载数据时程序中的 GUI 响应很差;有什么方法可以改善这个吗?

发布于 2024-12-11 10:17:18 字数 1374 浏览 3 评论 0原文

我编写了一个程序,它(除其他外)使用 TCP 从 LAN 上的服务器下载多个大文件。该程序在 Linux、MacOS/X 下运行良好,通常在 Windows 下也运行良好(它使用 Qt 进行 GUI 并使用直接套接字调用进行网络连接),但在某些 Windows 机器上,下载量似乎太大,机器无法处理,我想知道是否有人对为什么会这样以及可以采取什么措施有任何想法。

下载文件时,我的程序会生成一个单独的 I/O 线程,该线程基本上只是处于循环中,通过 TCP 下载数据并将其写入文件,每次调用 QFile:write() 写入 128KB。每个文件通常有数百兆字节长,典型的下载会话会写出几十个这样的文件。请注意,I/O 线程独立于 GUI 线程运行,因此我不希望它对 GUI 的性能产生太大影响(如果有的话)——尤其是在多核 PC 上运行时。

所讨论的 PC 是 Core-2Duo Quad Q6600,运行频率为 2.40GHz,具有 4GB RAM。它运行的是 Windows 7 Ultimate SP1,32 位。它通过千兆位以太网连接接收数据,并将其写入 232GB 内部 Hitachi ATA 驱动器的 NTFS 格式引导分区上的文件。

症状是,有时在下载过程中(看似随机),程序的 GUI 会一次无响应 10 到 30 秒,并且窗口的标题栏通常会附加“(无响应)”。然后症状将再次消失,下载将再次正常进行。另一个症状是下载过程中桌面非常缓慢...例如,如果我单击“开始”按钮,开始菜单将需要大约 30 秒的时间才能填充,而不是像我预期的那样几乎立即填充。

请注意,任务管理器显示大量可用内存,但它确实显示 4 个核心之一的 CPU 使用率出现短暂峰值,达到 100%,同时也看到了问题。

数据通过千兆位以太网到达,如果我的程序只是接收数据并将其丢弃(而不将其写入硬盘),则机器可以毫不费力地保持大约 96MB/秒的恒定下载速率。然而,如果我将接收到的数据写入文件,下载速率会降低至约 37MB/秒,并且开始出现上述症状。

有趣的是,出于好奇,我在事件循环开始之前将此调用添加到了 I/O 线程的入口函数中:

SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL);

当我这样做时,“(没有响应)”症状消失了,但下载速度加快了减少到仅~25MB/秒。

所以我的问题是:

  • 有谁知道当硬盘驱动器处于重写入负载时可能导致 GUI 偶发挂起的原因是什么?

  • 既然机器上有三个空闲核心,为什么降低 I/O 线程的优先级会导致下载速率下降这么多?我认为在这种情况下,即使是较低优先级的线程也会有足够的 CPU 可用。

  • 是否有任何方法可以在不导致 Windows 桌面响应能力和/或我的应用程序的 GUI 响应能力出现问题的情况下获得最大下载速率?

I've written a program that (among other things) downloads multiple large files from a server on the LAN, using TCP. This program runs fine under Linux, MacOS/X, and generally under Windows as well (it uses Qt for the GUI and straight sockets calls for networking), but on certain Windows machines the download appears to be too much for the machine to handle, and I'm wondering if anyone has any ideas as to why that is and what can be done about it.

When downloading files, my program spawns a separate I/O thread that basically just sits in a loop, downloading data over TCP and writing it to a file, writing 128KB per call to QFile:write(). Each file is typically several hundred megabytes long, and a typical download session writes out several dozen of these files. Note that the I/O thread runs independently of the GUI thread, so I wouldn't expect it to affect GUI's performance much if at all -- especially not when running on a multicore PC.

The PC in question is a Core-2Duo Quad Q6600 running at 2.40GHz, with 4GB of RAM. It's running Windows 7 Ultimate SP1, 32-bit. It is receiving data over a Gigabit Ethernet connection and writing it to files on the NTFS-formatted boot partition of the 232GB internal Hitachi ATA drive.

The symptom is that sometimes during a download (seemingly at random) the program's GUI will become non-responsive for 10 to 30 seconds at a time, and often the title bar of the window will have "(not responding)" appended to it. The symptom will then clear up again and the download will proceed normally again. Another symptom is that the desktop is extremely sluggish during the download... for example, if I click on the "Start" button, the Start menu will take ~30 seconds to populate, instead of being populated near-instantaneously as I would expect.

Note that Task Manager shows plenty of free memory, but it does show short spikes of CPU usage to 100% one one of the 4 cores, at the same time the problems are seen.

The data is arriving over Gigabit Ethernet, and if I have my program just receive the data and throw it away (without writing it to the hard drive), the machine can maintain a constant download rate of about 96MB/sec without breaking a sweat. If I write the received data to a file, however, the download rate decreases to about 37MB/sec, and the symptoms described above start to appear.

The interesting thing is that just for curiosity's sake I added this call to my I/O thread's entry function, just before the beginning of its event loop:

SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL);

When I did that, the "(not responding)" symptoms cleared, but then download speed was reduced to only ~25MB/sec.

So my questions are:

  • Does anyone know what might be causing the sporadic hangups of the GUI when the hard drive is under a heavy write-load?

  • Why does lowering the I/O thread's priority cause the download rate to drop so much, given that there are three idle cores on the machine? I would think that even a lower-priority thread would have plenty of CPU available in this situation.

  • Is there any way to get a maximum download rate without causing Windows' desktop responsiveness and/or my app's GUI responsiveness to suffer problems?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

燕归巢 2024-12-18 10:17:18

没有看到任何代码很难回答,但这似乎与处理器有关,并且您的下载线程没有为其他线程留下任何空间来执行其他操作。

看来它永远不会等待,而且网卡的驱动程序写得不好。
您确定您的线程在没有数据传入时进入空闲状态吗?
在具有单处理器的操作系统中, for (;;) {} 将消耗 100% 的 cpu,如果它不断地与内核对话,它可能会停止其他进程或其他线程来执行此操作,特别是如果存在错误或非常糟糕的行为在您的情况下的某些网卡驱动程序中。

可能将线程优先级设置为低于正常优先级,您会要求操作系统减少使用线程的频率,这是通过神奇的组合提供的,使事情不会挂起太多。
检查一下代码,也许你忘记了什么?

检查添加 sleep(0) 来强制操作系统在某个时候屈服于另一个线程是否会让事情变得更好,但这是一个临时修复,您应该找到为什么您的线程消耗 100% cpu(如果是)。

Without seeing any code is hard to answer but this seems to be something related to processors and the fact that your download thread is not leaving any space for other threads to performs other operations.

It seems it never waits and that the driver of the network card is not well written.
Are you sure your thread is entering in an idle state when there is no data incoming?
In OS with a single processor a for (;;) {} will consume 100% cpu and if it talks continuously with the kernel it may stops other processes or other threads for doing that, especially if there is a bug or a very bad behaviour in some network card driver in your case.

Probably putting the thread priority below normal you are asking the OS to use your thread less often, this gives by a magical combination of things that allow things to not hang too much.
Check the code, maybe you are forgetting something?

Check if adding a sleep(0) to force the OS to yield to another thread sometime will make things better, but this is a temporary fix, you should find why your thread is consuming 100% cpu, if it is.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文