代码之家  ›  专栏  ›  技术社区  ›  David Gladfelter

C++中COM的QuealUsWorkWork项

  •  2
  • David Gladfelter  · 技术社区  · 15 年前

    我有一个性能问题,客户在我的C++应用程序的DOM中创建数以百计的特定对象“FoO”。每个foo实例都有自己的异步工作队列和自己的线程。很明显,这是不成比例的。

    我需要在工作队列中共享线程,我不想重新发明轮子。我需要支持XP,所以我不能使用Vista/Win7线程池。处理每个队列项需要做的工作包括在多线程COM单元中进行COM调用。xp线程池的文档说明可以在线程工作函数回调中使用MTA单元调用coInitializeEx()。我已经编写了一个测试应用程序,并验证了这一点。我让这个应用程序在WorkItem回调函数中运行了100万次迭代,其中包含或不包含coInitializeEx/couninitialize对。使用Coinit*通话需要35秒,而不使用Coinit*通话需要5秒。这对我的应用程序来说是太多的开销了。因为线程池是每个进程的,并且第三方代码在我的进程中运行,所以我假设每个线程一次coInitializeEx()而从不couninitialize()是不安全的。

    考虑到所有这些,有没有任何方法可以使用win32线程池?我是否遗漏了一些东西,或者xp线程池对于高性能的COM应用程序来说是相当无用的?我只需要创建自己的线程共享系统吗?

    2 回复  |  直到 13 年前
        1
  •  1
  •   Rick    15 年前

    你核实了这么久的事情了吗?也就是说,它是对coInitializeEx()的调用吗?每个任务绝对不需要调用CoInitialize一次。你也不知道你产生了多少线程,也就是说,如果你在双核上运行并且你的工作是CPU密集型的,不要期望超过2倍的加速,如果你的工作是 不是 CPU密集型,然后它在等待一些资源(内存、磁盘、网络),加速也会受到类似的限制,如果对该资源持有锁,可能会更糟。

    如果您可以使用Visual Studio 2010,请看一下并行模式库和异步代理库,有几个工具可以帮助您减少编写代码的工作量。

    如果不能,至少可以尝试在tls中放置一个表示COM是否已在该线程上初始化的令牌,并在不需要时使用该令牌来绕过对coInitialize的调用。

        2
  •  1
  •   John Knoeller    15 年前

    我假设每个线程一次coInitializeEx()而从不couninitialize()是不安全的。

    如果一个线程退出而不调用couninitialize,Windows将进行清理,我们知道这是有效的,因为如果没有,线程崩溃或中止时将不会进行清理。

    所以,这种黑客行为造成问题的唯一方法是,有人试图将需要一套STA公寓的工作项目排队,这似乎不太可能。

    我很想去买。

    推荐文章