Win32 消息泵与 MFC 消息映射,哪个更快? C++

Posted

技术标签:

【中文标题】Win32 消息泵与 MFC 消息映射,哪个更快? C++【英文标题】:Win32 Message Pump vs MFC Message Maps, which is faster? C++ 【发布时间】:2009-05-25 14:57:07 【问题描述】:

不是从易用性,而是从性能的角度。 MFC 消息映射是否比典型的消息泵更快?

【问题讨论】:

我相信您正在使用“消息泵”(从队列中检索消息并分派到每个窗口 proc),但您正在考虑“窗口 proc”(处理每条消息都完成了)。 【参考方案1】:

MFC 封装了 Win32 消息传递,因此 MFC 会稍微慢一些。也就是说,如果您正在处理 UI 小部件,性能不是问题。

【讨论】:

【参考方案2】:

它们不可能更快,因为它们只是普通 Windows 消息泵的封装。话虽如此,它们在反射消息和自定义控件的消息泵封装方面确实有很大帮助,而且开销可以忽略不计,因此如果您有一个复杂的 UI 项目,从长远来看它可能是值得的。

【讨论】:

【参考方案3】:

我不得不不同意(到目前为止)其他 2 位受访者声称 MFC 消息泵性能较差的原因仅仅是因为它包装了普通的旧 C 消息泵:MFC 使用的技术与包含一个巨大的简单窗口 proc 的技术非常不同switch(message) 语句。

MFC 消息泵确实依赖于 Win32 消息循环(它必须)。但实现非常不同:基于钩子,由 MFC 在内部处理消息的调度,而不是依赖于 DispatchMessage() API。

MFC 使用映射将消息匹配到处理程序:O(log n)。从这个角度来看,在某些情况下,这可能比大型且糟糕编译的 switch(message) 语句更快:O(n)。

此外,识别正确的窗口对象可能比 DispatchMessage() 更快,因为 Windows 不是开源的,我们无法确定。

但这不太可能,特别是考虑到额外的代码,例如命令路由、空闲处理和 MFC 代码处理的各种极端情况......以及编译器足够聪明以有效地实现大型 @987654321 的事实@ 语句!

话虽如此,15 年多来人们一直认为性能影响并不显着。

【讨论】:

是的,我也认为理论上地图应该更快,但最终它真的取决于每个特定的实现。例如,由于switch 语句仅接受 consts 值作为 case 标签,因此 switch 被编译为静态跳转表,这可能比大型映射更快(如果某些消息比其他消息使用得更多,则甚至更多)。 您有多确定 MFC 的消息匹配接近 O(log n)?宏扩展为未排序的结构数组,因此将消息映射到特定处理程序的搜索仍然应该是线性的(只是由于额外的间接性而不是简单的优化开关而更慢)。【参考方案4】:

塞尔吉写道:

MFC 消息泵确实依赖 在 Win32 消息循环上(它必须)。 但是实现非常 不同:基于钩子,调度 MFC 内部处理的消息数 而不是依靠 DispatchMessage() API。

我不确定这是否正确。如果您查看 MFC thrdcore.cpp 文件,您会看到这个函数:

  BOOL AFXAPI AfxInternalPumpMessage()
  
     _AFX_THREAD_STATE *pState = AfxGetThreadState();


     .......... snip ...........


     // process this message
     if (pState->m_msgCur.message != WM_KICKIDLE 
         && !AfxPreTranslateMessage(&(pState->m_msgCur)))
     
        ::TranslateMessage(&(pState->m_msgCur));
        ::DispatchMessage(&(pState->m_msgCur));
     
     return TRUE;
  

此函数由 MFC PumpMessage 函数调用,您可以看到它使用 Win32 DispatchMessage API,就像任何其他 Win32 应用程序一样。

【讨论】:

以上是关于Win32 消息泵与 MFC 消息映射,哪个更快? C++的主要内容,如果未能解决你的问题,请参考以下文章

重构 MFC 消息映射以包含完全限定的成员函数指针

027.MFC_映射消息

消息映射 MFC:继承多个消息映射

MFC如何给菜单添加消息映射

猎豹MFC--消息映射

MFC编程入门之五(MFC消息映射机制概述)