1

我编写了一个程序,该程序(除其他外)使用 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 响应出现问题的情况下获得最大下载速率?

4

1 回答 1

0

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

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

可能将线程优先级低于正常值,您会要求操作系统不经常使用您的线程,这是通过一种神奇的组合来实现的,它可以让事情不会挂太多。检查代码,也许你忘记了什么?

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

于 2011-10-21T23:24:57.700 回答