调用Thread.SpinWait时会被内联吗?

时间:2013-10-31 08:34:48

标签: c# clr

我有以下代码:

while(flag)
{
  Thread.SpinWait(1);
}

以下是SpinWait

Rotor(sscli20\clr\src\vm\comsynchronizable.cpp)的实施情况
FCIMPL1(void, ThreadNative::SpinWait, int iterations)
{
    WRAPPER_CONTRACT;
    STATIC_CONTRACT_SO_TOLERANT;

    for(int i = 0; i < iterations; i++)
        YieldProcessor();
}
FCIMPLEND

调用后会Thread.SpinWait内联吗?

如果没有,在每个循环周期中,它将花费更多时间在stack operations(push and pop)上并消耗更多的CPU执行资源。

如果是,clr如何实现ThreadNative::SpinWait作为标准函数指令序列实现,包括堆栈操作(推送和弹出)?

通过测试Eren,在调试模式下不会出现内联。 是否可以优化并生成内联代码?

摘要:谢谢你的回答。我希望有一天clr可以通过一种机制(如MethodImplOptions.InternalCall)内联预编译代码。然后它可以消除堆栈操作并花费大部分时间检查标志和旋转等待(比nop消耗更少的cpu资源)。

2 个答案:

答案 0 :(得分:4)

最好试试看。示例代码:

static void Main(string[] args)
{
    while (true) 
        Thread.SpinWait(1);
} 

优化的反汇编显示:

<强> 86

00000000  push        ebp 
00000001  mov         ebp,esp 
00000003  mov         ecx,1 
00000008  call        6F11D3FE 
0000000d  jmp         00000003 

<强> 64

00000000  sub         rsp,28h 
00000004  mov         ecx,1 
00000009  call        000000005F815434 
0000000e  jmp         0000000000000004 
00000010  add         rsp,28h 
00000014  ret 

因此在任何一种情况下都有无内联

也许我错过了一些东西,但我不太明白为什么你关心堆栈操作,因为旋转CPU会消耗周期(整个目的是收益)。

答案 1 :(得分:2)

不,抖动无法内联预编译的C ++代码,只能以IL开头的托管代码。

这与SpinWait()调用完全无关。旋转等待的目的是让处理器执行代码而不是支付线程上下文切换的成本。期望 flag 将在10,000 cpu周期或更少的时间内变为 false 什么类代码并不重要。 CALL是执行代码的好方法。