мультиплексирование
Oct. 27th, 2012 11:03 pmЕго ещё нужно уметь тестировать, оказывается.
Клиент написан на NIO, бросается тривиальными запросами, идёт спать с помощью Thread.sleep, чтобы гарантировать нужный arrival rate, и пользуется Selector.select.

Удивительно здесь то, что Response Time не зависит от arrival rate, и то, что другой клиент, написанный полностью на blocking IO и с 6x потоков, добивается более низкого Response Time (на графике не указан). Но если у нас 24 ядра, то что будет делать этот клиент с 75 потоками? Думаю, здесь начинаются какие-то трюки ОС, когда оно пытается не снимать с ядра потоки, даже если они в blocking IO. Тогда даже хотя потоков и 75, но запросов в каждый момент времени-то всего 24, а потому только вот эти 24 сокета и могут стать read-ready, и потому клиент с blocking IO кажется выигрывает. Но это не честный тест, он biases сокеты, и не умеет задавать arrival rate.
Ещё один confounding factor - вы видите, что throughput застрял на 70+К и дальше не смог пройти? Это примерно тот же throughput, что и у blocking IO клиента. Это не показалось бы странным, если бы не следующий эксперимент.
Тот же NIO клиент, но не спит: все Thread.sleep заменены на пустой цикл, проверяющий текущее время, а Selector.select заменено на Selector.trySelect в цикле. Всё направлено на то, чтобы потоки никогда с ядра не слезали.

Вот теперь мы получаем разные Response time для разных arrival rate (ура!) и Response time для 70+К запросов получается такой же, как и для клиента с blocking IO. И мы, оказывается, можем повышать throughput до 200К, а может, и больше.
Остаётся объяснить, что это за разноцветные точки. Это два разных способа мультиплексировать входящие соединения на сервере. Теория говорит, что красные должны победить, но график нам кагбы намекает.
А вот как выглядит картинка, когда тот же неблокирующий бессонный NIO клиент распределяет arrivals по Пуассону.

Нужно из этого извлечь какой-нибудь урок.
Клиент написан на NIO, бросается тривиальными запросами, идёт спать с помощью Thread.sleep, чтобы гарантировать нужный arrival rate, и пользуется Selector.select.

Удивительно здесь то, что Response Time не зависит от arrival rate, и то, что другой клиент, написанный полностью на blocking IO и с 6x потоков, добивается более низкого Response Time (на графике не указан). Но если у нас 24 ядра, то что будет делать этот клиент с 75 потоками? Думаю, здесь начинаются какие-то трюки ОС, когда оно пытается не снимать с ядра потоки, даже если они в blocking IO. Тогда даже хотя потоков и 75, но запросов в каждый момент времени-то всего 24, а потому только вот эти 24 сокета и могут стать read-ready, и потому клиент с blocking IO кажется выигрывает. Но это не честный тест, он biases сокеты, и не умеет задавать arrival rate.
Ещё один confounding factor - вы видите, что throughput застрял на 70+К и дальше не смог пройти? Это примерно тот же throughput, что и у blocking IO клиента. Это не показалось бы странным, если бы не следующий эксперимент.
Тот же NIO клиент, но не спит: все Thread.sleep заменены на пустой цикл, проверяющий текущее время, а Selector.select заменено на Selector.trySelect в цикле. Всё направлено на то, чтобы потоки никогда с ядра не слезали.

Вот теперь мы получаем разные Response time для разных arrival rate (ура!) и Response time для 70+К запросов получается такой же, как и для клиента с blocking IO. И мы, оказывается, можем повышать throughput до 200К, а может, и больше.
Остаётся объяснить, что это за разноцветные точки. Это два разных способа мультиплексировать входящие соединения на сервере. Теория говорит, что красные должны победить, но график нам кагбы намекает.
А вот как выглядит картинка, когда тот же неблокирующий бессонный NIO клиент распределяет arrivals по Пуассону.

Нужно из этого извлечь какой-нибудь урок.