2

我有以下代码:

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

以下是SpinWaitin的实现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 优化和生成内联代码?

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

4

2 回答 2

4

最好试试看。示例代码:

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

优化后的反汇编显示:

x86:

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

x64:

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

所以在这两种情况下都没有内联

也许我遗漏了一些东西,但我不太明白为什么你关心堆栈操作,因为旋转 CPU 无论如何都会消耗周期(整个目的是屈服)。

于 2013-10-31T09:02:55.940 回答
2

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

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

于 2013-10-31T09:32:35.877 回答