У меня есть многопоточная серверная программа C++, которая использует MSXML6 и непрерывно анализирует сообщения XML, а затем применяет подготовленное преобразование XSLT для создания текста. Я запускаю это на сервере с 4 процессорами. Каждый поток полностью независим и использует свой собственный объект преобразования. Между потоками нет совместного использования каких-либо COM-объектов.
Это работает хорошо, но проблема заключается в масштабируемости. Во время работы:
- с одним потоком я получаю около 26 синтаксических анализов + преобразований в секунду на поток.
- с 2 потоками я получаю около 20/с/поток,
- с 3 нитями, 18/с/резьба.
- с 4 нитями, 15/с/резьба.
Поскольку между потоками не было ничего общего, я ожидал почти линейной масштабируемости, поэтому он должен быть в 4 раза быстрее с 4 потоками, чем с 1. Вместо этого он всего в 2,3 раза быстрее.
Это похоже на классическую проблему соперничества. Я написал тестовые программы, чтобы исключить возможность конфликта в моем коде. Я использую класс DOMDocument60 вместо класса FreeThreadedDOMDocument, чтобы избежать ненужной блокировки, поскольку документы никогда не передаются между потоками. Я тщательно искал какие-либо доказательства ложного совместного использования строки кэша, и их нет, по крайней мере, в моем коде.
Еще одна подсказка: скорость переключения контекста > 15 к/с для каждого потока. Я предполагаю, что виновником является диспетчер памяти COM или диспетчер памяти в MSXML. Возможно, у него есть глобальная блокировка, которую необходимо получить и снять при каждом выделении/освобождении памяти. Я просто не могу поверить, что в наши дни диспетчер памяти не написан таким образом, чтобы хорошо масштабироваться в многопоточных многопроцессорных сценариях.
Кто-нибудь знает, что вызывает это утверждение или как его устранить?