Я пытаюсь найти, где лежит узкое место на сервере С#, которое недоиспользует процессор. Я думаю, что это может быть из-за плохой производительности ввода-вывода диска и не имеет ничего общего с самим приложением, но у меня возникают проблемы с фактом из этого предположения.
Приложение считывает сообщения из локальной очереди MSMQ, выполняет некоторую обработку для каждого сообщения и после обработки сообщений отправляет ответные сообщения в другую локальную очередь MSMQ.
Я использую асинхронный цикл для чтения сообщений из очереди, откладывая их как можно быстрее и отправляя их для обработки с помощью Task.Run, чтобы запускать обработку каждого сообщения (и не ждать этого Task.Run.. просто прикрепление к нему только ошибки, чтобы ошибка журнала). Каждое сообщение обрабатывается одновременно, то есть нет необходимости ждать, пока сообщение будет полностью обработано до обработки следующего.
В конце обработки сообщения я использую метод отправки MessageQueue (как-то асинхронный, но не очень, потому что он должен ждать на диске записи перед возвратом -see System.Messaging - почему MessageQueue не предлагает асинхронную версию Отправить).
Для тестов я размещаю 100 тыс. сообщений в очереди (около 100 МБ общего объема для сообщений 100 КБ), а затем запускаю программу. На двух моих персональных компьютерах (SSD HD на одном и на SATA2 HD с другой с iQ CPU quadcores -8 логической proc) я достигаю ~ 95% использования ЦП на протяжении всего жизненного цикла программы (удаление сообщений 100 тыс., Обработка их и отправка ответов). Сообщения удаляются как можно быстрее, обрабатываются как можно быстрее (здесь задействован процессор), а затем ответ для каждого сообщения, отправленного в другую локальную очередь.
Теперь на виртуальной машине, работающей с двухъядерным процессором без HT (не знаю, что является основным диском, но кажется гораздо менее эффективным, чем мины... во время теста, с Perfmon я могу видеть avg disk sec/write arround 10-15 ms на этой виртуальной машине, тогда как на моих персональных машинах arms 2ms), когда я работаю на той же скамейке, я достигаю ~ 55% CPU (когда я запускаю одну и ту же скамью на машине, не отправляя ответные сообщения в очередь, я достигаю ~ 90% CPU).
Я действительно не понимаю, в чем проблема. Понятно, что отправкой сообщения в очередь является проблема и замедляет глобальную обработку программы (и удаление очереди для обработки сообщений), но почему это следует учитывать, что я использую Task.Run для запуска обработки каждого отправленного сообщения и, в конечном счете, отсылка ответа, я бы не ожидал, что процессор будет недостаточно использоваться. Если ни один поток не отправляет сообщение, он блокирует другие потоки для запуска на одном и том же ядре, пока он ждет возврата (запись на диск), и в этом случае, возможно, имеет смысл считать, что время ожидания намного выше, чем на моих персональных компьютерах, но поток ожидание ввода-вывода не должно препятствовать запуску других потоков.
Я действительно пытаюсь понять, почему я не достигаю, по крайней мере, 95% -ного использования процессора на этой машине. Я слепо говорю, что это связано с более низкой производительностью диска, но все же я не понимаю, почему это приведет к недоиспользованию процессора, учитывая, что я запускаю обработку одновременно с помощью Task.Run. Это также может быть некоторая системная проблема, полностью не связанная с диском, но учитывая, что MessageQueue.Send, похоже, является проблемой и что этот метод в конечном итоге записывает сообщения в файл с отображением памяти + диск, я не вижу, откуда может возникнуть проблема производительности кроме диска.
Конечно, проблема в производительности системы по мере того, как программа максимизирует использование ЦП на моих собственных компьютерах, но мне нужно найти, что узкое место находится именно в системе VM, и почему именно это влияет на concurrency/скорость моего приложения.
Любая идея?