2008-11-28 61 views
0

我有一個多線程服務器C++程序,它使用MSXML6並不斷分析XML消息,然後應用準備好的XSLT轉換來生成文本。我在有4個CPU的服務器上運行它。每個線程都是完全獨立的,並使用自己的變換對象。線程之間不共享任何COM對象。MSXML XSL轉換mutthreaded性能爭用

這很好,但問題是可擴展性。運行時:

  1. 有一個線程,我得到每個線程每秒約26個parse +轉換。
  2. 與2個線程,我得到約20/s /線程,
  3. 與3線程,18/s /線程。
  4. 4線程,15/s /線程。

線程之間沒有共享我期望接近線性的可擴展性,所以它應該是4線程的4倍,而不是1線。相反,它只有2.3倍的速度。

它看起來像一個經典的爭用問題。我編寫了測試程序來消除我的代碼中存在爭用的可能性。我正在使用DOMDocument60類而不是FreeThreadedDOMDocument類,以避免不必要的鎖定,因爲文檔永遠不會在線程之間共享。我很難看到任何緩存行虛假共享的證據,至少在我的代碼中沒有任何證據。

另一個線索是,每個線程的上下文切換率大於15k/s。 我猜測罪魁禍首是MSXML中的COM內存管理器或內存管理器。也許它有一個全局鎖,必須獲取並釋放每個內存分配/釋放。我無法相信,在當今這個時代,內存管理器的寫入方式並不是多線程多CPU場景中可以很好地擴展的方式。

有沒有人有任何想法是什麼導致這個爭論或如何消除它?

回答

1

感謝您的答案。我最終實施了兩個建議的組合。

我在C#中創建了一個COM + ServicedComponent,它將其作爲COM +下的一個單獨的服務器進程託管,並使用XSLCompiledTransform運行轉換。 C++服務器使用COM連接到此外部進程,並將其發送給XML並獲取轉換後的字符串。這使性能翻了一番。

2

對於基於堆的內存管理器(基本的malloc/free)來說,使用單個互斥量是相當普遍的,這有相當好的理由:堆內存區域是一個單一的連貫數據結構。

有替代的內存管理策略(例如分層分配器),沒有這個限制。您應該研究自定義MSXML使用的分配器。

或者,您應該研究從多線程體系結構轉移到多進程體系結構,併爲每個MSXML工作程序提供單獨的進程。由於您的MSXML工作人員將字符串數據作爲輸入和輸出,因此您沒有序列化問題。

總結:使用多進程體系結構,它更適合您的問題,並且可以更好地擴展。

+0

+1爲多進程而不是多線程。 – 2008-11-28 19:23:15

1

MSXML使用BSTR,BSTR在堆管理中使用全局鎖。幾年前它給我們帶來了大量的多用戶應用程序的麻煩。

我們在我們的應用程序中刪除了對XML的使用,您可能無法執行此操作,因此使用替代XML解析器可能會更好。