我编写了一个程序,该程序(除其他外)使用 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。它运行的是 32 位 Windows 7 Ultimate SP1。它通过千兆以太网连接接收数据并将其写入 232GB 内部日立 ATA 驱动器的 NTFS 格式引导分区上的文件。
症状是有时在下载过程中(似乎是随机的)程序的 GUI 会在 10 到 30 秒内无响应,并且窗口的标题栏通常会附加“(无响应)”。然后症状将再次消失,下载将再次正常进行。另一个症状是下载过程中桌面非常缓慢......例如,如果我点击“开始”按钮,开始菜单将需要大约 30 秒来填充,而不是像我期望的那样几乎立即填充.
请注意,任务管理器显示了大量可用内存,但它确实显示了 CPU 使用率的短暂峰值,达到 100% 的 4 个内核之一,同时也看到了问题。
数据通过千兆以太网到达,如果我的程序只是接收数据并将其丢弃(不将其写入硬盘驱动器),机器可以保持约 96MB/秒的恒定下载速率而不会出汗。但是,如果我将接收到的数据写入文件,下载速率会降低到大约 37MB/秒,并且开始出现上述症状。
有趣的是,出于好奇,我在 I/O 线程的入口函数中添加了这个调用,就在它的事件循环开始之前:
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL);
当我这样做时,“(无响应)”症状消失了,但下载速度降低到只有 ~25MB/秒。
所以我的问题是:
有谁知道当硬盘驱动器处于繁重的写入负载时可能导致 GUI 偶尔挂断的原因是什么?
既然机器上有三个空闲内核,为什么降低 I/O 线程的优先级会导致下载率下降这么多?我认为在这种情况下,即使是较低优先级的线程也会有足够的 CPU 可用。
有没有办法在不导致 Windows 桌面响应和/或我的应用程序的 GUI 响应出现问题的情况下获得最大下载速率?