2008-11-28 4 views
0

У меня есть многопотоковая серверная программа на C++, которая использует MSXML6 и непрерывно анализирует XML-сообщения, а затем применяет подготовленное преобразование XSLT для создания текста. Я запускаю это на сервере с 4 процессорами. Каждый поток полностью независим и использует свой собственный объект преобразования. Не существует совместного использования каких-либо COM-объектов среди потоков.MSXML XSL Transformation mutithreaded конкуренция производительности

Это хорошо работает, но проблема в масштабируемости. При работе:

  1. с одним потоком, я получаю около 26 разводов + преобразования в секунду на поток.
  2. с 2 потоками, я получаю около 20/с/нить,
  3. с 3 резьбами, 18/с/нить.
  4. с 4 резьбами, 15/с/резьба.

Ничего общего между потоками Я ожидал почти линейной масштабируемости, поэтому он должен быть в 4 раза быстрее с 4 потоками, чем с 1. Вместо этого он всего в 2,3 раза быстрее.

Это похоже на классическую проблему конфликтов. Я написал тестовые программы, чтобы исключить возможность конфликта в моем коде. Я использую класс DOMDocument60 вместо FreeThreadedDOMDocument, чтобы избежать ненужной блокировки, поскольку документы никогда не используются совместно между потоками. Я много искал никаких доказательств ложного обмена кеш-линией и, по крайней мере, в моем коде нет.

Другая подсказка, скорость переключения контекста составляет> 15 к/с для каждой нити. Я предполагаю, что виновником является менеджер памяти COM или менеджер памяти в MSXML. Возможно, у него есть глобальная блокировка, которая должна быть приобретена и выпущена для каждого распределения/освобождения памяти. Я просто не могу поверить, что в наши дни менеджер памяти не написан таким образом, чтобы он хорошо масштабировался в многопоточных сценариях с несколькими процессорами.

Кто-нибудь знает, что вызывает это утверждение или как его устранить?

ответ

1

Спасибо за ответы. Я закончил реализацию двух предложений.

Я сделал COM + ServicedComponent в C#, разместил его как отдельный серверный процесс под COM + и использовал XSLCompiledTransform для запуска преобразования. Сервер C++ подключается к этому внешнему процессу с помощью COM и отправляет его XML и возвращает преобразованную строку. Это удвоило производительность.

2

Общепринято для управления памятью на основе кучи (ваш основной malloc/free) для использования одного мьютекса, для этого есть достаточно веские причины: область памяти кучи представляет собой единую согласованную структуру данных.

Существуют альтернативные стратегии управления памятью (например, иерархические распределители), которые не имеют этого ограничения. Вы должны изучить настройку распределителя, используемого MSXML.

В качестве альтернативы вам следует исследовать переход от многопоточной архитектуры к многопроцессорной архитектуре с отдельными процессами для каждого рабочего MSXML. Поскольку ваш работник MSXML принимает строковые данные в качестве ввода и вывода, у вас нет проблемы с сериализацией.

Вкратце: используйте многопроцессорную архитектуру, она лучше подходит для вашей проблемы, и она будет масштабироваться лучше.

+0

+1 для многопроцессорного процесса вместо многопоточного. – 2008-11-28 19:23:15

1

MSXML использует BSTR, которые используют глобальную блокировку в управлении кучей. Это вызвало у нас массу проблем для многопользовательского приложения несколько лет назад.

Мы удалили использование XML в нашем приложении, возможно, вы не сможете это сделать, поэтому вам может быть лучше использовать альтернативный синтаксический анализатор XML.