2

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

我需要在工作队列之间共享线程,我不想重新发明轮子。我需要支持XP,所以不能使用Vista/Win7线程池。处理每个队列项需要完成的工作包括在多线程 COM 单元中进行 COM 调用。XP 线程池的文档说可以在线程工作者函数回调中使用 MTA 单元调用 CoInitializeEx()。我编写了一个测试应用程序并验证它是否有效。我让应用程序在 WorkItem 回调函数中使用和不使用 CoInitializeEx/CoUninitialize 对运行了 100 万次迭代。CoInit* 调用需要 35 秒,没有调用需要 5 秒。这对我的应用程序来说开销太大了。由于线程池是每个进程的,并且第 3 方代码在我的进程中运行,我假设它不是

鉴于所有这些,有什么方法可以使用 Win32 线程池吗?是我遗漏了什么,还是 XP 线程池对于高性能 COM 应用程序毫无用处?我只需要创建自己的线程共享系统吗?

4

2 回答 2

1

我假设每个线程一次 CoInitializeEx() 并且永远不会 CoUninitialize() 是不安全的。

如果线程在没有调用 CoUninitialize 的情况下退出,Windows 将进行清理,我们知道这是可行的,因为如果不这样做,线程崩溃或中止时将不会进行清理。

因此,这种黑客攻击可能导致问题的唯一方法是有人试图将需要 STA 公寓的工作项目排队,这似乎不太可能。

我很想去。

于 2010-02-04T01:37:37.853 回答
1

您是否验证了需要这么长时间的原因?即它是对 CoInitializeEx() 的调用吗?您绝对不需要为每个任务调用一次 CoInitialize。你也没有说你产生了多少线程,即如果你在双核上运行并且你的工作是 CPU 密集型的,不要期望超过 2 倍的加速,如果你的工作不是CPU 密集型那么它正在等待一些资源(内存、磁盘、网络)和加速将同样受到限制,如果为该资源持有锁,可能会变得更糟。

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

If you can't you can at least try placing a token in TLS that represents whether COM has been initialized on that thread and use the presence of this token to bypass your calls to CoInitialize when they aren't needed.

于 2010-02-04T14:31:39.450 回答