Производительность многопоточного клиентского сетевого приложения - PullRequest
0 голосов
/ 03 декабря 2018

Я реализовал клиентское приложение, которое отправляет запросы на сервер.Как это работает, можно описать очень просто.Я указываю количество потоков.Каждый из этих потоков неоднократно отправляет запросы на сервер и ждет ответа.Throughput

Я составил общую пропускную способность клиента для различного числа потоков.Количество виртуальных клиентов не важно, меня интересует максимальная, насыщенная производительность, в самом правом углу графика.

Я удивлен, потому что Я не ожидал, что производительность будет масштабироваться с количеством потоков .Действительно, большая часть процессорного времени затрачивается на блокировку ввода-вывода в Java (блокирование сокетов), поскольку связь клиент-сервер имеет задержку 1 мс, а клиент работает на на 8-ядерном компьютере .

Я искал решения в Интернете, этот ответ по Quora , по-видимому, подразумевает, что время ожидания для блокировки ввода-вывода можно запланировать для других задач.Является ли это верно, особенно для сокетов блокировки Java?В таком случае, почему я не получаю линейное масштабирование с количеством потоков?

Если это важно, я запускаю это приложение в облаке.Кроме того, это часть более крупного приложения, но я определил этот компонент как узкое место всей установки.

1 Ответ

0 голосов
/ 04 декабря 2018

Я искал решения онлайн, этот ответ на Quora, кажется, подразумевает, что время ожидания для блокировки ввода-вывода может быть запланировано для использования для других задач.Верно ли это, особенно для блокирующих сокетов Java?

Обычные потоки Java отображаются в потоки уровня ОС один на один.Они эквивалентны.Так что да, это верно для Java, и на самом деле любой другой язык.Если только он не использует Green Threads или неблокирующий ввод / вывод.

В таком случае, почему бы мне не получить линейное масштабирование с количеством потоков?

Подумайте о том, что вы делаете, с точки зрения процессора.Процессор выполняет дорогостоящее переключение контекста и позволяет запускать некоторые потоки.Этот поток использует ЦП в течение очень короткого промежутка времени для подготовки сетевого вызова, а затем он блокируется на длительное время (миллисекунды довольно много для ЦП, работающего на частоте 3 ГГц).

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

Сравните это с потоком, выполняющим задачу с привязкой к ЦП .Переключение контекста занимает то же время.Но когда задается задача, связанная с ЦП, ей удается долго использовать ЦП, что делает переключение контекста более дешевым по сравнению с ним.Это увеличивает общую загрузку ЦП.

Итак, с одной стороны, вы видите более высокие скорости с каждым новым потоком, потому что вы по существу выполняете больше параллельных операций ввода-вывода.С другой стороны, каждый новый поток добавляет стоимость.Таким образом, предельное преимущество каждого дополнительного потока каждый раз немного меньше.Если вы продолжите добавлять потоки, в какой-то момент вы даже достигнете точки, где скорость будет падать с каждым новым потоком.

...