我有一个带有伪代码的 ASP.NET 页面:
while (read)
{
Response.OutputStream.Write(buffer, 0, buffer.Length);
Response.Flush();
}
任何请求此页面的客户端都将开始下载二进制文件。此时一切正常,但客户端没有下载速度限制,因此将上面的代码更改为:
while (read)
{
Response.OutputStream.Write(buffer, 0, buffer.Length);
Response.Flush();
Thread.Sleep(500);
}
速度问题现在已经解决了,但是在100个并发客户端接连连接(每个新连接之间延迟3秒)的测试下,当客户端数量增加时CPU使用率会增加,当有70~80个并发客户端CPU时达到 100% 并且拒绝任何新连接。其他机器上的数字可能不同,但问题是为什么 Thread.Sleep() 占用大量 CPU,有没有什么方法可以在不增加 CPU 的情况下加快客户端的运行速度?
我可以在 IIS 级别执行此操作,但我需要从我的应用程序内部进行更多控制。
最佳答案
让我们看看迈克尔的回答是否合理。
现在,Michael 明智地指出 Thread.Sleep(500)
不应该在 CPU 方面消耗太多。理论上这一切都很好,但让我们看看在实践中是否可行。
static void Main(string[] args) {
for(int i = 0; i != 10000; ++i)
{
Thread.Sleep(500);
}
}
运行此程序时,应用程序的 CPU 使用率徘徊在 0% 标记附近。
Michael 还指出,由于 ASP.NET 必须使用的所有线程都处于休眠状态,因此它必须生成新线程,并提出这是昂贵的。让我们尝试不 sleep ,而是做大量的产卵:
static void Main(string[] args) {
for(int i = 0; i != 10000; ++i)
{
new Thread(o => {}).Start();
}
}
我们创建了很多线程,但它们只是执行一个空操作。这会占用大量 CPU,即使线程没有执行任何操作。
不过,线程总数永远不会很高,因为每个线程的生存时间都很短。让我们将两者结合起来:
static void Main(string[] args) {
for(int i = 0; i != 10000; ++i)
{
new Thread(o => {Thread.Sleep(500);}).Start();
}
}
将这个我们已经证明 CPU 使用率很低的操作添加到每个线程会增加更多的 CPU 使用率,因为线程会增加。如果我在调试器中运行它,它会将 CPU 推到接近 100%。如果我在调试器之外运行它,它的性能会好一些,但这只是因为它在有机会达到 100% 之前抛出了内存不足异常。
因此,问题不在于 Thread.Sleep 本身,而是让所有可用线程休眠的副作用会强制创建越来越多的线程来处理其他工作,正如 Michael 所说。
关于c# - 为什么 Thread.Sleep() 占用大量 CPU?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3886171/