当使用内核对象同步运行在不同CPU上的线程时,相对于其他OS,使用Windows Server 2008 R2时是否可能会花费一些额外的运行时间?
编辑:并且从答案中发现,该问题还应包括短语“当以较低的CPU利用率运行时”。我在自己对这个问题的回答中包含了更多信息。
背景
我致力于使用共享内存和信号量在进程之间进行通信的产品(当两个进程在同一台计算机上运行时)。关于Windows Server 2008 R2的性能问题的报告(此后我简称为Win2008R2)使我发现,与其他操作系统相比,在Win2008R2的两个线程之间共享信号量相对较慢。
复制它
我能够通过在两个线程上同时运行以下代码来重现它:
for ( i = 0; i < N; i++ )
{
WaitForSingleObject( globalSem, INFINITE );
ReleaseSemaphore( globalSem, 1, NULL );
}
使用将双启动到Windows Server 2003 R2 SP2和Windows Server 2008 R2的计算机进行测试,以上代码段在Win2003R2计算机上的运行速度比Win2008R2快7倍(Win2003R2为3秒,Win2008R2为21秒)。
测试的简单版本
以下是上述测试的完整版本:
#include <windows.h>
#include <stdio.h>
#include <time.h>
HANDLE gSema4;
int gIterations = 1000000;
DWORD WINAPI testthread( LPVOID tn )
{
int count = gIterations;
while ( count-- )
{
WaitForSingleObject( gSema4, INFINITE );
ReleaseSemaphore( gSema4, 1, NULL );
}
return 0;
}
int main( int argc, char* argv[] )
{
DWORD threadId;
clock_t ct;
HANDLE threads[2];
gSema4 = CreateSemaphore( NULL, 1, 1, NULL );
ct = clock();
threads[0] = CreateThread( NULL, 0, testthread, NULL, 0, &threadId );
threads[1] = CreateThread( NULL, 0, testthread, NULL, 0, &threadId );
WaitForMultipleObjects( 2, threads, TRUE, INFINITE );
printf( "Total time = %d\n", clock() - ct );
CloseHandle( gSema4 );
return 0;
}
更多细节
我更新了测试,以强制线程运行一次迭代,并在每个循环处强制切换到下一个线程。每个线程发出信号通知下一个线程在每个循环的末尾运行(循环式)。我还更新了它,以使用自旋锁代替信号量(这是一个内核对象)。
我测试过的所有机器都是64位机器。我将测试大部分编译为32位。如果构建为64位,则总体运行速度会稍快一些,并且会更改一些比率,但最终结果是相同的。除了Win2008R2,我还尝试使用Windows 7 Enterprise SP 1,Windows Server 2003 R2 Standard SP 2,Windows Server 2008(非R2)和Windows Server 2012 Standard。
以下是更新后的测试中的一些实际数字(时间以毫秒为单位):
+----------------+-----------+---------------+----------------+
| OS | 2 cpu sem | 1 cpu sem | 2 cpu spinlock |
+----------------+-----------+---------------+----------------+
| Windows 7 | 7115 ms | 1960 ms (3.6) | 504 ms (14.1) |
| Server 2008 R2 | 20640 ms | 2263 ms (9.1) | 866 ms (23.8) |
| Server 2003 | 3570 ms | 1766 ms (2.0) | 452 ms (7.9) |
+----------------+-----------+---------------+----------------+
测试中的2个线程中的每一个都运行1百万次迭代。这些睾丸都在相同的机器上运行。 Win Server 2008和Server 2003编号来自双启动计算机。 Win 7机器具有完全相同的规范,但物理机器却不同。在这种情况下,该机器是具有Core i5-2520M 2.5GHz的Lenovo T420笔记本电脑。显然不是服务器类机器,但是在真正的服务器类硬件上我得到了类似的结果。括号中的数字是第一列与给定列的比率。
是否有任何解释说明为什么这个OS似乎会为跨CPU的内核级同步引入额外的费用?还是您知道一些可能会影响此设置的配置/调整参数?
尽管这样做会使冗长且冗长,但我可以发布增强版的测试代码,如果有人愿意的话,上述数字也来自此代码。这将显示循环逻辑的执行和测试的自旋锁版本。
延伸背景
试图回答有关为什么以这种方式完成事情的一些不可避免的问题。而且我是一样的...当我阅读帖子时,我常常想知道为什么我什至在问。因此,这里有一些尝试可以弄清楚:
最佳答案
从评论中拉出答案:
也许服务器未设置为高性能电源计划? Win2k8可能具有不同的默认值。默认情况下,许多服务器不是默认的,这会严重影响性能。
OP确认这是根本原因。
这是造成这种现象的一个有趣原因。当我做完全不同的事情时,这个想法突然浮现在脑海中。