SpinWait的性能高于Thread.Sleep
2017-11-28 13:33
423 查看
在进行多线程开发时,我们经常会用到Thread.Sleep(timeout_ms)来等待或者腾出时间来让其他线程处理。不过,即使我们把timeout_ms设置为0,Thread.Sleep还是会执行等待操作。这就让人很纳闷了,我明明指定的等待时间是0毫秒,为什么还会执行等待呢?
这时因为当我们调用Thread.Sleep时,是让内核暂停处理当前的线程,然后再看需要等待多久,当发现等待时间是timeout_ms时,就等待timeout_ms长的时间,然后内核继续运行该线程。即使timeout_ms为0,由于这个过程中内核已经执行了暂停和恢复的动作,所以会消耗时间。这样也就说明了,即时Thread.Sleep等待的时候是0,还是会有等待的过程。
而如果使用自旋等待就会不一样。下面先看一下代码和执行结果。
[csharp]
view plain
copy
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
namespace SpinWaitTest
{
class Program
{
private static int _count = 1000;
private static int _timeout_ms = 10;
static void Main(string[] args)
{
//NoSleep();
ThreadSleepInThread();
SpinWaitInThread();
Console.ReadLine();
}
private static void NoSleep()
{
Thread thread = new Thread(() =>
{
var sw = Stopwatch.StartNew();
for (int i = 0; i < _count; i++)
{
}
Console.WriteLine("No Sleep Consume Time:{0}", sw.Elapsed.ToString());
});
thread.IsBackground = true;
thread.Start();
}
private static void ThreadSleepInThread()
{
Thread thread = new Thread(() =>
{
var sw = Stopwatch.StartNew();
for (int i = 0; i < _count; i++)
{
Thread.Sleep(_timeout_ms);
}
Console.WriteLine("Thread Sleep Consume Time:{0}", sw.Elapsed.ToString());
});
thread.IsBackground = true;
thread.Start();
}
private static void SpinWaitInThread()
{
Thread thread = new Thread(() =>
{
var sw = Stopwatch.StartNew();
for (int i = 0; i < _count; i++)
{
SpinWait.SpinUntil(() => true, _timeout_ms);
}
Console.WriteLine("SpinWait Consume Time:{0}", sw.Elapsed.ToString());
});
thread.IsBackground = true;
thread.Start();
}
}
}
运行结果
看看结果会发现,Thread.Sleep的时间比SpinWait多了近50万倍,这相差实在是太大了。有人会说了,Thread.Sleep是执行了10ms*1000=10s的等待,而SpinWait.SpinUntil的条件直接是true,所以相当于没有等待,时间自然会少了很多。那好,我们把_timeout_ms设成0,然后再看运行结果。
我们看到Thread.Sleep的等待时间还是要比SpinWait的长了近10倍,这是为什么呢?
这是因为SpinWait.SpinUntil在执行等待时,会先进行自旋。所谓自旋就是在CPU运转的周期内,如果条件满足了,就不会再进入内核等待(即暂停该线程,等待一段时间后,再继续运行该线程),如果条件不满足,才进入内核等待。这样一来,SpinWait会比Thread.Sleep多运行一次的CPU周期,再进入等待。因为CPU周期是很短的(现在一般的电脑都有2.1GHZ以上),所以这个等待对时间影响不大,却可以提升很大的性能。
可以参看MSDN的说明http://msdn.microsoft.com/zh-cn/library/system.threading.thread.spinwait(v=vs.110).aspx
这时因为当我们调用Thread.Sleep时,是让内核暂停处理当前的线程,然后再看需要等待多久,当发现等待时间是timeout_ms时,就等待timeout_ms长的时间,然后内核继续运行该线程。即使timeout_ms为0,由于这个过程中内核已经执行了暂停和恢复的动作,所以会消耗时间。这样也就说明了,即时Thread.Sleep等待的时候是0,还是会有等待的过程。
而如果使用自旋等待就会不一样。下面先看一下代码和执行结果。
[csharp]
view plain
copy
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
namespace SpinWaitTest
{
class Program
{
private static int _count = 1000;
private static int _timeout_ms = 10;
static void Main(string[] args)
{
//NoSleep();
ThreadSleepInThread();
SpinWaitInThread();
Console.ReadLine();
}
private static void NoSleep()
{
Thread thread = new Thread(() =>
{
var sw = Stopwatch.StartNew();
for (int i = 0; i < _count; i++)
{
}
Console.WriteLine("No Sleep Consume Time:{0}", sw.Elapsed.ToString());
});
thread.IsBackground = true;
thread.Start();
}
private static void ThreadSleepInThread()
{
Thread thread = new Thread(() =>
{
var sw = Stopwatch.StartNew();
for (int i = 0; i < _count; i++)
{
Thread.Sleep(_timeout_ms);
}
Console.WriteLine("Thread Sleep Consume Time:{0}", sw.Elapsed.ToString());
});
thread.IsBackground = true;
thread.Start();
}
private static void SpinWaitInThread()
{
Thread thread = new Thread(() =>
{
var sw = Stopwatch.StartNew();
for (int i = 0; i < _count; i++)
{
SpinWait.SpinUntil(() => true, _timeout_ms);
}
Console.WriteLine("SpinWait Consume Time:{0}", sw.Elapsed.ToString());
});
thread.IsBackground = true;
thread.Start();
}
}
}
运行结果
看看结果会发现,Thread.Sleep的时间比SpinWait多了近50万倍,这相差实在是太大了。有人会说了,Thread.Sleep是执行了10ms*1000=10s的等待,而SpinWait.SpinUntil的条件直接是true,所以相当于没有等待,时间自然会少了很多。那好,我们把_timeout_ms设成0,然后再看运行结果。
我们看到Thread.Sleep的等待时间还是要比SpinWait的长了近10倍,这是为什么呢?
这是因为SpinWait.SpinUntil在执行等待时,会先进行自旋。所谓自旋就是在CPU运转的周期内,如果条件满足了,就不会再进入内核等待(即暂停该线程,等待一段时间后,再继续运行该线程),如果条件不满足,才进入内核等待。这样一来,SpinWait会比Thread.Sleep多运行一次的CPU周期,再进入等待。因为CPU周期是很短的(现在一般的电脑都有2.1GHZ以上),所以这个等待对时间影响不大,却可以提升很大的性能。
可以参看MSDN的说明http://msdn.microsoft.com/zh-cn/library/system.threading.thread.spinwait(v=vs.110).aspx
相关文章推荐
- SpinWait的性能高于Thread.Sleep
- Thread.Sleep和Timer性能比较
- Thread.Sleep和Timer性能比较
- Thread.Sleep和Timer性能比较
- Thread.Sleep和Timer性能比较
- 理解 Thread.Sleep 函数
- Java Thread(线程)案例详解sleep和wait的区别
- Thread类的sleep()方法和对象的wait()方法都可以让线程暂停执行,它们有什么区别?
- Linux内核:kthread_create(线程)、SLEEP_MILLI_SEC
- 阿里2014校招笔试题(南大)——利用thread和sleep生成字符串的伪随机序列
- 多个线程共享变量的例子,线程为什么要Thread.sleep
- Thread.sleep (转)
- Thread.Sleep 函数 理解
- Thread.sleep() & SystemClock.sleep()
- Thread--线程休眠sleep
- Thread 常搞混的几个概念sleep、wait、yield、interrupt
- [原创] 难道调用ThreadPool.QueueUserWorkItem()的时候,真是必须调用Thread.Sleep(N)吗?
- Jmeter之性能压测Stepping Thread Group 逐步增加并发数 阶梯式加压并发 (十五)
- Thread.sleep Thread能够去掉
- Thread 常搞混的几个概念sleep、wait、yield、interrupt (转)