Windows 安全模式运行简单程序(至少)比普通模式快三倍?

13

最近我在进行很多基准测试,偶然发现了一个非常令人不安/有趣/新奇的事情。通过进行更深入的研究(我自己都不敢相信),似乎Windows XP(以及可能所有其他版本)运行程序的速度比安全模式下慢三倍左右。

以这个小程序为例:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)
{

    long    i,j,k;

    printf ("Starting...\n");

    k = 12;

    for (i = 0; i < 20000; i++)
        for (j = 100000; j > 0; j--)
            k = k * 12;

    printf ("Done... k =%d", k);     // just using k here to prevent the whole block isn't optimized away.

    return 0;
}

在我的2.4 GHz电脑上,在安全模式下执行需要约2.5秒,而在正常模式下执行需要约8秒。(ThreadPriority = TIMECRITICAL,ProcessClass = REALTIME)即使我在这个非常的Windows正常模式下编译和启动该代码时,它的执行速度更快(大约5.5秒)。
我还进行了大量的CPU周期测量,实际上,安全模式下的结果更像是根据处理的指令数量所期望的结果。
那么我错过了什么?有人能解决这个谜题吗?
感谢所有的指针和提示。 谢谢。
解决了!对不起,这个问题与我的糟糕的Alienware M15x有关,由于某种原因,它会降低到其CPU功率的1/3,除非您使用邪恶的工具(ThrottleStop.exe)将其恢复到正常速度。非常抱歉浪费你们的时间。 :(

1
你是如何测量时间的?代码中没有测量代码。此外,你确定整个循环不会被优化掉吗?编译器可能能够在编译时计算出k的值。 - AshleysBrain
是的,为了简单起见,我省略了那个测量步骤。实际上,我已经不再相信任何东西了,所以我只是让循环足够大,可以手持秒表坐在那里。这确实是2.5秒对8-8.5秒。我也查看了机器代码 - 所以,它没有被优化掉 - 而且:这是同样的代码在正常模式下运行1次 - 在安全模式下运行1次。 - Roman Pfneudl
@Roman Pfneudl,这很有趣,特别是因为您没有进行任何磁盘密集型操作。但是您是否尝试停止您的反病毒软件/反恶意软件并查看是否有所改善? - Chris Taylor
我停止了几乎所有的东西 - 我的电脑上也没有运行任何防病毒/恶意软件程序 - 另外:这种行为在我的另一台电脑上也可以重现。即使是因为恶意软件之类的原因,也不可能占用66%的CPU(我确实使用了100个周期的例程进行了CPU周期测量,并且它们在Windows正常模式下稳定在100个周期,而在安全模式下则需要35个周期)。 - Roman Pfneudl
你尝试过在安全模式和正常模式下使用进程资源管理器来查看系统内部真正加载了哪些内容吗? - darioo
是的,它说:正常模式下90-95%的时间处于空闲状态。 - Roman Pfneudl
8个回答

7

已解决!很抱歉,这个问题和我那烂掉的外星人m15x有关,出现了某种原因导致其CPU功率降至三分之一 - 除非使用邪恶工具(ThrottleStop.exe)将其提升至正常速度。非常抱歉浪费了你们的时间。 :(


2
非常好。我一直在关注这个帖子,很想知道结果是什么。我很高兴它可以被解释清楚。 - Chris Taylor
是啊,我也是。那东西几乎把我逼疯了,让我感觉到满脑子都是阴谋。 :) - Roman Pfneudl
感谢您回来并解释,即使这不是您所期望的。 - AshleysBrain

3
你是否在多台电脑上重现了此问题?(我假设当你说尝试在VMware / Linux上时,是指在同一台Windows计算机上作为VMware主机,在其中运行Linux作为其​​内部的客户端)。
如果您只在一台计算机上看到了这种情况,那么您可能有一个减慢速度的驱动程序,该驱动程序在安全模式下未被加载。
(或其他某些软件,但根据您关于CPU似乎空闲且代码不与操作系统交互的��述,很可能是驱动程序,除非某些东西延迟了实际的printf输出。)。
例如,某些驱动程序可能会保持低级别锁定,从而防止正确的任务切换,或者某些东西可能正在使用延迟printf调用的资源。两者都不一定在CPU使用方面可见。

我完全将printf函数排除在外,因为它是另一个复杂的io锁定/解锁函数,并使用几个仅执行计算任务的函数进行测试,将块测量到仅有4个汇编指令。好的,我认为我必须提供一个更好的示例来更好地展示我的意思。 - Roman Pfneudl

2

以下几点需要注意:

  • 你说你用秒表来测量时间,但这不会给出你的进程真实耗时,你需要正确地对代码进行分析。
  • 你尝试过其他程序吗?
  • 试一下这个测试:在两个XP虚拟机中,一个虚拟机以安全模式启动,另一个虚拟机以正常模式启动,在大约相同的时间内启动两个虚拟机中的程序,并测量每个虚拟机所需的CPU时间(而非钟表时间)。

我使用rdtsc来测量CPU周期。我将ProcessAffinity设置为仅使用1个处理器,因为我知道如果不这样做,rdtsc有时会出现问题。我测量了简单代码的小部分,结果显示出33%/ 100%的行为。我甚至测量了一个简单的sleep(2000),在两种情况下都得出了约1952毫秒的结果。所以,这证明rdtsc至少在某种程度上是正确工作的->它只是一直提供这种疯狂的差异。我担心启动复杂的程序也无法帮助我。我不会从中获得任何有用的信息。 - Roman Pfneudl
我没有说要启动一个复杂的程序,只是另一个不同的程序。它会告诉您这个应用程序是否有特定问题还是更一般性的问题。您还需要进行适当的分析以了解时间花费在哪里。 - hhafez

2

DEP在安全模式下运行吗?我想知道它是否是某种安全/沙盒或类似的东西。不过这很有趣。


DEP在安全模式下仍然可以运行。它是一种安全机制,用于保护计算机免受恶意软件攻击。

不太可能 - 它只针对Windows进程开启(至少在我的机器上是这样)。 - Roman Pfneudl

2

就像Leo Davidson所说的那样,这可能是由于在安全模式下未加载的驱动程序导致的。

1)可能是硬件驱动程序:两台计算机具有相同的硬件配置吗?

2)甚至可能是恶意软件(带有rootkit!):这意味着恶意驱动程序将在正常模式下隐藏自己,因此您可以比较在安全和正常模式下获取的sytem32\drivers\中文件列表及其大小/MD5。您可以使用http://www.virustotal.com/扫描任何文件。


不会的,它不应该减慢程序运行速度,大概会减慢66%左右。驱动程序和恶意软件也只是在某些时候获取其CPU周期的进程。这最多只会导致不稳定的结果。 - Roman Pfneudl
1
驱动程序不是进程;它们在每个进程内部运行,并且可以对事物进行相当大的改变。另一个与驱动程序无关的要点是,在检查资源使用时,确保查看所有用户的进程。 - Leo Davidson

2

我相当确定这是你的电脑出了特殊问题。

我在旧的XP netbook上运行了编译为MSVC 10 Release模式的代码,普通模式下比安全模式快一点,虽然没有精确测量,但在普通模式下大约需要8秒钟,在安全模式下需要10秒钟。

令人惊讶的是,在你的电脑上,普通模式下花费的时间与旧的单核Atom CPU相同。你没有提到你使用的电脑型号,但我认为它应该比netbook更快,所以可能存在问题。


你说得对 - 我刚刚发现我的外星人m15x有这些问题,哈哈。抱歉。 - Roman Pfneudl

0

我猜这是因为安全模式下运行的后台进程少得多,因此对CPU和内存的使用压力也更小。


5
不,我想这绝对不是重点。Windows不能稳定地占用2/3的处理能力。 - Roman Pfneudl
但是为什么小程序需要更多时间? - the_drow
这并不是针对小程序的问题 - 我只是拿了一个非常小的程序作为例子,以便更容易地重现 - 我的疯狂直觉是Windows将处理器置于某种“过度调试”模式,以便能够捕获更多的异常或其他问题。 - Roman Pfneudl

0
如果你在使用C++,你可以使用QueryPerformanceFrequency和QueryPerformanceCounter来精确地计时一段代码,例如:
#include <time.h>
#include <windows.h>

LARGE_INTEGER startTimer, endTimer, frequency;//declare some big numbers to use in timers
double timeTakenInSeconds;

int main()
{
    //start timer: 
    QueryPerformanceFrequency(&frequency);//retrieves the frequency of the high-resolution performance counter(if exsists on this hardware)
    QueryPerformanceCounter(&startTimer);//retrieves the current value of the high-resolution performance counter(in counts)

    //do something that you want to time here eg call a sorting method


    QueryPerformanceCounter(&endTimer);//endtimer
    timeTakenInSeconds = (endTimer.QuadPart-startTimer.QuadPart) / (double)frequency.QuadPart;//Work out time difference
    cout <<"somthing took:  \t" << timeTakenInSeconds << " seconds" <<endl;//print the time takken

    return 0;
}

2
OP 知道如何计时代码,他想知道为什么在正常模式下比安全模式慢。 - darioo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接