我遇到了性能问题,客户端在我的C ++应用程序的DOM中创建了数百种特定类型的对象“Foo”。每个Foo实例都有自己的异步工作队列和自己的线程。显然,这不会扩大规模。
我需要在工作队列中共享线程,我不想重新发明轮子。我需要支持XP,所以我不能使用Vista / Win7线程池。处理每个队列项所需的工作涉及在多线程COM公寓中进行COM调用。 XP线程池的文档说可以在线程工作器函数回调中使用MTA单元调用CoInitializeEx()。我写了一个测试应用程序,并验证了这是有效的。我在WorkItem回调函数中使用和不使用CoInitializeEx / CoUninitialize对使app运行了100万次迭代。 CoInit *呼叫需要35秒,没有它们需要5秒。这对我的应用来说太多开销了。由于线程池是按进程进行的,第三方代码在我的进程中运行,我假设每个线程对CoInitializeEx()一次都不安全,而且从不CoUninitialize()。
鉴于所有这些,有什么办法可以使用Win32线程池吗?我错过了什么,或者XP线程池对于高性能COM应用程序是否无用?我是否只需要创建自己的线程共享系统?
答案 0 :(得分:1)
我假设每个线程一次对CoInitializeEx()不安全,而且从不CoUninitialize()。
如果线程退出而不调用CoUninitialize,Windows将清理,我们知道这是有效的,因为如果没有,则在线程崩溃或中止时不会进行清理。
因此,这个黑客可能导致问题的唯一方法是有人试图排队需要STA公寓的工作项,这似乎不太可能。
我很想去争取它。
答案 1 :(得分:1)
你确认了这么长时间的服用吗?即它是对CoInitializeEx()的调用吗?您绝对不需要为每个任务调用一次CoInitialize。你也没有说你产生了多少线程,即如果你在双核上运行并且你的工作是CPU密集型的,那么你的工作不是 CPU密集,然后它等待一些资源(内存,磁盘,网络)和加速将同样受到约束,如果为该资源保持锁定可能会更糟。
如果您可以使用Visual Studio 2010,请查看并行模式库和异步代理库,有一些工具可以帮助减少编写代码。
如果你不能,你至少可以尝试在TLS中放置一个令牌,表示COM是否已在该线程上初始化,并且在不需要时使用此令牌的存在来绕过对CoInitialize的调用。