C++ 中带有 COM 的 QueueUserWorkItem

发布于 2024-08-20 17:08:33 字数 585 浏览 13 评论 0原文

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

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

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

I have a performance issue where clients are creating hundreds of a particular kind of object "Foo" in my C++ application's DOM. Each Foo instance has its own asynchronous work queue with its own thread. Obviously, that doesn't scale.

I need to share threads amongst work queues, and I don't want to re-invent the wheel. I need to support XP, so I can't use the Vista/Win7 thread pool. The work that needs to be done to process each queue item involves making COM calls in the multi-threaded COM apartment. The documentation for the XP thread pool says that it is okay to call CoInitializeEx() with the MTA apartment in the thread worker function callback. I've written a test app and verified that this works. I made the app run 1 million iterations with and without a CoInitializeEx/CoUninitialize pair in the WorkItem callback function. It takes 35 seconds with the CoInit* calls and 5 seconds without them. That's way too much overhead for my application. Since the thread pool is per-process and 3rd-party code runs in my process, I'm assuming it isn't safe to CoInitializeEx() once per thread and never CoUninitialize().

Given all of that, is there any way that I can use the Win32 thread pool? Am I missing something, or is the XP thread pool pretty useless for high-performance COM applications? Am I just going to have to create my own thread-sharing system?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

风渺 2024-08-27 17:08:33

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

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

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

Have you verified what is taking so long? i.e. is it the call to CoInitializeEx()? You definitely don't need to call CoInitialize once per task. You also don't say how many threads you spawn, i.e. if your running on a dual core and your work is CPU intensive don't expect more than a 2x speedup, and if your work isn't CPU intensive then it's waiting on some resource (memory, disk, net) and speedups will be similarly constrained, perhaps made worse if there is a lock being held for that resource.

If you can use Visual Studio 2010 take a look at the Parallel Pattern Library and Asynchronous Agents Library, there are a couple tools that can help make this take less code to write.

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.

苏辞 2024-08-27 17:08:33

我假设每个线程使用 CoInitializeEx() 一次而不是 CoUninitialize() 是不安全的。

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

因此,这次黑客攻击可能导致问题的唯一原因是有人试图对需要 STA 公寓的工作项目进行排队,但这似乎不太可能。

我很想尝试一下。

I'm assuming it isn't safe to CoInitializeEx() once per thread and never CoUninitialize().

Windows will clean up if a thread exits without calling CoUninitialize, we know this works because if it didn't there would be no cleanup when threads crash or are aborted.

So the only way this hack could cause a problem is of someone was trying to queue work items that needed an STA apartment, which seem unlikely.

I'd be tempted to go for it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文