Подтвердить что ты не робот

Улучшение производительности NIO по сравнению с традиционным IO в Java

Я видел много статей/блогов о том, что Java NIO является лучшим решением по сравнению с традиционным Java IO.

Но сегодня один из моих сотрудников показал мне этот блог http://mailinator.blogspot.com/2008/02/kill-myth-please-nio-is-not-faster-than.html. Мне интересно, сделал ли кто-либо из сообщества Java такой сравнительный тест, связанный с производительностью Java NIO.

4b9b3361

Ответ 1

NIO vs IO - довольно интересная тема для обсуждения.

По моему опыту, эти два являются двумя разными инструментами для двух разных заданий. Я слышал, что IO упоминается как подход "Thread per Client" и NIO как подход "Один поток для всех клиентов", и я нахожу имена, а не на 100% точными, достаточно подходящими.

Реальная проблема с NIO и IO, как я вижу, связана с масштабируемостью.

Сетевой уровень NIO будет (должен?) использовать один поток для обработки селектора и отправки заданий чтения/записи/принятия в другие потоки. Это позволяет потоку, обрабатывающему селектор ( "Селекторный поток" ), ничего не делать, кроме только этого. Это позволяет значительно быстрее реагировать при работе с большим количеством (обратите внимание на отсутствие фактических номеров) клиентов. Теперь, когда NIO начинает разваливаться, это когда сервер получает так много сообщений read/write/accept, что селекторный поток постоянно работает. Любые дополнительные задания после этого и сервер начинают отставать. Кроме того, поскольку все задания чтения/записи/приема обрабатываются в потоке селектора, добавление дополнительных процессоров в микс не улучшит производительность.

Сетевой уровень IO, вероятно, будет использовать подход 1 потока на сокет, включая прослушивающий сокет. Таким образом, количество потоков напрямую пропорционально количеству клиентов. Под умеренным количеством клиентов этот подход работает очень хорошо. Стоимость, которую платит, используя этот подход, приходит в виде стоимости потока. если у вас 2000 клиентов, подключенных к серверу... у вас есть потоки по меньшей мере 2001 года. Даже в четырехъядерном чипе с 6 ядрами на чип-машину у вас есть только 24 обрабатывающих узла (48, если вы считаете HyperThreading), чтобы обрабатывать эти потоки 2001 года. Мгновенное копирование всех этих потоков требует времени процессора и ram, но даже если вы используете пул потоков, вам все равно придется оплачивать стоимость переключения контекстов ЦП при переходе от потока к потоку. Это может стать очень уродливым при высоких нагрузках на сервер, и, если он не правильно закодирован, может остановить работу всей машины. С положительной стороны, добавление процессоров к машине улучшит производительность в этом случае.

Теперь все хорошо и хорошо, но в абстрактном виде, потому что в моем описании нет цифр, чтобы помочь принять решение с IO или NIO. Это связано с тем, что еще больше переменных:

  • Срок службы клиента? Короче или долго?
  • Количество ожидаемых данных для каждого клиента? Много мелких кусков или несколько огромных кусков?
  • Сколько клиентов предполагается подключать одновременно?
  • На какой ОС вы работаете и какую JVM вы используете? Оба фактора относятся к расходам на Thread и poll.

Просто пища для размышлений. Чтобы ответить на вопрос о том, что быстрее, NIO или IO: оба и ни одно:)

Ответ 2

A быстрее, чем B часто очень упрощенное представление, а иногда и неправильное.

NIO не автоматически быстрее обычного IO.

Некоторые операции потенциально ускоряются с использованием NIO, и вы можете масштабировать для многих сетевых подключений намного проще с помощью NIO (потому что вам не нужен один поток для каждого соединения).

Но NIO - это не волшебство, "ускоряющее работу" - переключатель, который нужно применять ко всему.

Ответ 3

NIO используется не потому, что он быстрее, а потому, что он имеет лучшую масштабируемость, особенно количество клиентов.

IO (Блокирование ввода/вывода IO/Stream IO) обычно является одним потоком для каждого соединения, чтобы лучше реагировать на клиентов. Предположим, вы используете один поток для (блокирования) прослушивания/(блокирования) чтения/обработки/(блокировки) записи для всех клиентов, так же как Starbucks обслуживает всех клиентов в одном окне, клиентов Starbucks (ваш клиенты) будут получать нетерпение (тайм-аут).

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

NIO (Нет. Блокировка IO/Block IO который используется) использует шаблон Reactor для обработки событий ввода-вывода. В этом случае вы можете использовать один поток для блокировки/прослушивания | читать | процесс | писать. Тогда блокировка клиентов (период ожидания) не будет влиять друг на друга.

Обратите внимание, что IO и NIO могут использовать многопоточные потоки для использования большего количества ресурсов процессора, более подробно в Doug lee introduction.

Ответ 4

Статья, которую вы цитируете, составляет три года. Он использовал Java 1.4.2 (4).

С тех пор выходят Java 5, 6 и 7.

Огромные изменения внутри JVM, а также библиотеки классов сделали все, что связано с сравнительным анализом 1.4.2, не имеющим отношения к делу.

Если вы начнете копать, вы также заметите, что различие между java.io и java.nio не совсем ясное. Многие вызовы java.io теперь разрешаются в классах java.nio.

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

Ответ 5

Проблема со статьей заключается в сравнении блокировки IO и неблокирующего NIO. В моих собственных тестах сравнение блокировки IO и блокировки NIO (более похоже на подобное) NIO на 30% быстрее.

Однако, если ваше приложение тривиально, как прокси-сервер, вряд ли это имеет значение. То, что делает приложение, гораздо важнее. И IO, и NIO были протестированы с до 10000 соединений.

Если вы хотите супер быстрый IO, вы можете использовать Asynch IO (Java 7+) с Infiniband (не дешево, но с меньшей задержкой)

Ответ 6

Кроме того, AFAIK, Java IO была переписана для использования NIO под-покрытиями (и у NIO больше функциональности). Microbenchmarks - всего лишь плохая идея, особенно когда они старые, как утверждает lavinio.

Ответ 7

Java NIO считается более быстрым, чем обычный IO, потому что:

  • Java NIO поддерживает неблокирующий режим. Неблокирующий IO быстрее, чем блокирование ввода-вывода, поскольку для каждого соединения не требуется выделенный поток. Это может значительно повысить масштабируемость, когда вам нужно обрабатывать множество одновременных подключений, поскольку потоки не очень масштабируемы.

  • Java NIO уменьшает количество копий данных, поддерживая буферы с прямой памятью. Можно читать и записывать сокеты NIO без какого-либо копирования данных. С традиционным Java IO данные копируются несколько раз между буферами сокетов и массивами байтов.

Ответ 8

Java NIO и модель реактора не очень важны для производительности сети, но о преимуществах, которые однопоточная модель может доставить в систему с точки зрения производительности и простоты. И это однопоточный подход может привести к значительному улучшению. Посмотрите здесь: Межспутниковая связь с задержкой менее 2 микросекунд

Ответ 9

Java IO включает в себя несколько конструкций и классов. Вы не можете сравнивать на таком общем уровне. В частности, NIO использует файлы с отображением памяти для чтения. Это теоретически ожидается немного быстрее, чем простое чтение файла BufferedInputStream. Однако, если вы сравниваете что-то вроде файла RandomAccess, то файл с отображением NIO-памяти будет намного быстрее.

Ответ 10

Нет причин, по которым одна быстрее, чем другая.

В модели с одним соединением за потоки в настоящее время страдает тот факт, что поток Java имеет большие издержки памяти - потоковый стек предварительно распределен по фиксированному (и большому) размеру. Это может быть и должно быть исправлено; то мы можем дешево создавать сотни тысяч потоков.