WH_CALLWNDPROC挂钩性能是否随Win10大幅降低(与Win7相比)?

时间:2019-05-07 16:54:18

标签: winapi windows-10

我们正在将工作站从Win7升级到Win10。在调查性能下降的报告时,我得出的结论是它是由第三方安装的WH_CALLWNDPROC挂钩引起的。

我是基于以下测试应用程序的结果(在Delphi 10 Seattle中完成)得出的结论

procedure TForm3.Button1Click(Sender: TObject);
var
  I: Integer;
  SW : TStopWatch;
begin
  sw := TStopWatch.StartNew;
  for I := 0 to 1000000 do
  begin
    if Combobox1.ItemIndex > 0 then
      Exit;
  end;
  sw.Stop;
  ShowMessage(sw.ElapsedMilliseconds.ToString);
end;

(对于那些不熟悉Delphi的人,TStopwatch使用QueryPerformanceFrequency / QueryPerformanceCounter API来获取经过的时间)

此方法的执行时间为

  • Win10:1485毫秒
  • Win7:4996毫秒

(注意:两台机器的硬件完全不同,因此无法真正比​​拟。)

现在,如果我在执行相同代码之前添加钩子

function MySystemWndProcHook(Code: Integer; wParam: WParam; lParam: LParam): LRESULT; stdcall;
begin
  Result := CallNextHookEx(FHook, Code, wParam, LParam);
end;

procedure TForm3.FormCreate(Sender: TObject);
begin
  FHook := SetWindowsHookEx(WH_CALLWNDPROC, @MySystemWndProcHook, 0, GetCurrentThreadId)
end;

执行时间变为:

  • Win10:19552毫秒(约长1300%)
  • Win7:8682毫秒(约长75%)

现在,正如我所提到的,两个工作站都在不同的硬件上,但是我不相信仅凭这一个就可以解释两者之间的差异。 Win10具有i7 cpu,而Win7具有i3。如果有的话,我希望i3受到更大的冲击(更少的缓存,更少的资源...)

那么,自Win7以来,WH_CALLWNDPROC挂钩的速度变慢了这么多吗? 快速的Google搜索似乎没有发现有关此问题的任何其他报告。有人可以复制我的结果吗? 如果无法复制它,那么任何人都不知道是什么设置/冲突的应用程序引起的? (已经尝试禁用Windows Defender实时扫描,但这并不影响性能。)

编辑:这已在Win10 1803 64位下进行了测试。测试应用程序本身是32位。

EDIT2:用64位编译的同一应用程序具有以下执行时间。

  • Win10:780毫秒/ 10201毫秒。
  • Win7:6419毫秒/ 9201毫秒。

EDIT3:有趣的是,以admin身份运行应用程序(32位)时:

  • Win10:12693毫秒/ 18028毫秒

(在另一个工作站上),以不同用户身份运行也会有所不同:

  • Win10(1809)/“标准用户”:9430/17440毫秒
  • Win10(1809)/系统:5220/10160毫秒(通过PsExec远程启动)

EDIT4:如果以管理员身份运行,则从USB密钥运行的应用程序比从硬盘运行的速度更快。 (注意:到目前为止,我仅在具有单个驱动器的系统上进行了测试。在这一点上,我不排除仅OS驱动器的速度较慢。)

EDIT5:我发现了很多有关这种情况的事情。 首先,运行“以管理员身份”(win10)会使应用程序安装WH_CALLWNDPROCRET挂钩。我还没有找到它的来源(操作系统,Delphi的框架,其他应用程序?)。仅仅运行该应用程序绝对不存在。

对性能的影响似乎并没有那么多,而是对SendMessage的影响。

我们正在与Microsoft保持联系,他们再现了类似的结果(在100k循环而不是1m的循环中):

  • Windows 7-不带钩0.018396秒。
  • Windows 10-不带钩0.025102秒。
  • Windows 7-带挂钩0.167941秒。
  • Windows 10-带钩1.105929秒。

(调查仍在进行中,到目前为止尚无结论)

这些结果还表明,我们的许多工作站的性能都比不涉及钩子时的性能差。

1 个答案:

答案 0 :(得分:1)

因此,WH_CALLWNDPROC和WH_CALLWNDPROCRET挂钩确实会大大降低性能。与Win7相比,Win10中的优势更多。

一些性能上的损失来自Spectre和Meltdown的缓解代码。微软的早期报告表明,其余的显然来自窗口管理器(win32k * .sys)中的锁争用。

对于我在调查中得到的奇怪结果:

  • 运行“以管理员身份”导致在我的应用程序中安装了一个额外的钩子,这说明了我目睹的速度缓慢
  • 我做过的许多测试都在通过远程管理工具访问的测试机中...恰好安装了全局WH_CALLWNDPROC / WH_CALLWNDPROCRET钩子本身,这使我的测试结果有缺陷。在本地运行会“修复”结果。因为我的应用程序是32位,而钩子是64位,所以花了我一段时间才找到有关它的信息,所以我的应用程序未收到有关它们的通知(但仍然会导致性能下降)。