我有一个多线程服务器 C++ 程序,它使用 MSXML6 并不断解析 XML 消息,然后应用准备好的 XSLT 转换来生成文本。我在具有 4 个 CPU 的服务器上运行它。每个线程都是完全独立的,并使用自己的变换对象。线程之间不共享任何 COM 对象。
这很好用,但问题是可扩展性。运行时:
- 使用一个线程,每个线程每秒可以进行大约 26 次解析+转换。
- 有 2 个线程,我得到大约 20/s/线程,
- 带 3 个线程,18/s/线程。
- 有 4 个线程,15/s/线程。
由于线程之间没有共享任何东西,我期望接近线性的可伸缩性,因此 4 线程应该比 1 快 4 倍。相反,它只快 2.3 倍。
它看起来像一个经典的争用问题。我编写了测试程序来消除我的代码中存在争用的可能性。我正在使用 DOMDocument60 类而不是 FreeThreadedDOMDocument 类,以避免不必要的锁定,因为文档永远不会在线程之间共享。我努力寻找缓存行错误共享的任何证据,但至少在我的代码中没有。
另一个线索,每个线程的上下文切换速率 > 15k/s。我猜罪魁祸首是 COM 内存管理器或 MSXML 中的内存管理器。也许它有一个全局锁,必须为每个内存分配/释放获取和释放。我简直不敢相信,在这个时代,内存管理器的编写方式并不能很好地适应多线程多 CPU 场景。
有谁知道是什么导致了这种争用或如何消除它?