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