Проблема масштабируемости сервера С# в Linux
У меня есть сервер С#, разработанный как на Visual Studio 2010, так и на Mono Develop 2.8.NET Framework 4.0
Похоже, что этот сервер ведет себя намного лучше (с точки зрения масштабируемости) в Windows, чем в Linux.
Я проверил масштабируемость сервера на родной Windows (12 физических ядер) и 8 и 12 ядер Windows и Ubuntu Virtual Machines с помощью Apache ab tool.
Время отклика окон довольно плоское. Он начинает собираться, когда уровень concurrency приближается/преодолевает количество ядер.
По какой-то причине время ответа linux намного хуже. Они растут почти линейно, начиная с 5 уровня concurrency. Также 8 и 12 ядер Linux VM ведут себя аналогичным образом.
Итак, мой вопрос: почему он хуже работает на Linux? (и как я могу это исправить?).
Пожалуйста, взгляните на прилагаемый график, в котором показано усредненное время для выполнения 75% запросов в зависимости от запросов concurrency (диапазон диапазона установлен на 50% и 100%).
![time to fulfill 75% of the request as a function of the request concurrency]()
У меня такое ощущение, что это может быть связано с Mono Garbage Collector. Я пытался играть с настройками GC, но у меня не было успеха. Любое предложение?
Дополнительная дополнительная информация: сервер основан на прослушивателе HTTP, который быстро анализирует запросы и ставит их в очередь на пул потоков. Пул потоков отвечает за ответ на эти запросы с некоторой интенсивной математикой (вычисление ответа через ~ 10 секунд).
Ответы
Ответ 1
Вам нужно выделить, где проблема в первую очередь. Начните с мониторинга использования памяти с помощью HeapShot. Если это не память, то профиль вашего кода, чтобы определить трудоемкие методы.
Эта страница Рекомендации по производительности: создание более эффективных приложений .NET и Mono содержит некоторую полезную информацию, в том числе использование монопрофилирования.
Чрезмерная манипуляция строками и бокс часто являются "скрытыми" виновниками кода, который плохо масштабируется.
Ответ 2
Попробуйте сборщик мусора из сгенератора (и для этого рекомендуется Mono 2.11.x). Посмотрите страницу с моно-man для более подробной информации.
Ответ 3
Я не верю этому из-за GC. AFAIK побочные эффекты GC должны быть более или менее равномерно распределены по потокам.
Мое слепое предположение: вы можете исправить это, играя с API ThreadPool.SetMinThreads/SetMaxThreads.
Ответ 4
Я бы настоятельно рекомендовал вам сделать некоторые профили кода в отношении того, как долго работают отдельные методы. Весьма вероятно, что вы видите некоторые проблемы с блокировкой или аналогичные многопотоковые трудности, которые не обрабатываются моно. Использование ЦП и ОЗУ также поможет.
Ответ 5
Я считаю, что это может быть та же проблема, что и мы, отслеживая пул потоков и начальное поведение для новых потоков, а также ошибку в моно-реализации setMinThreads. Дополнительную информацию см. В моем ответе на эту тему: fooobar.com/questions/437300/...
Ответ 6
Если вы кодируете множество исключений, то mono будет в 10 раз быстрее, чем .NET