Функциональное программирование ввода / вывода и Java-программирование - PullRequest
0 голосов
/ 14 октября 2011

Привет: Мы используем Java для многопоточного приложения.Мы нашли узкое место в Java I / O.Имеет ли функциональное программирование, например, scala, лучшую пропускную способность ввода / вывода?У нас будет много процессорных ядер, в этом смысле бизнес-логика может обрабатываться очень быстро, но ввод-вывод будет узким местом.Есть ли хорошее решение?

Ответы [ 5 ]

11 голосов
/ 14 октября 2011

Поскольку Scala работает на виртуальной машине Java и (под капотом) использует Java API для ввода-вывода, переход на scala вряд ли обеспечит более высокую производительность, чем хорошо написанный код Java.

Что касаетсярешения, ваше описание проблемы слишком схематично, чтобы рекомендовать конкретные решения.

8 голосов
/ 14 октября 2011

Вы используете или пробовали Java nio (без блокировки)?Разработчики сообщают об увеличении производительности до 300%.

Производительность / полезность Java NIO FileChannel против FileOutputstream (см. Также)

7 голосов
/ 15 октября 2011

Обычно, когда люди жалуются на медленный ввод-вывод в Java, это медленный процесс ввода-вывода, а не сам ввод-вывод.Например, BufferedReader читает строки текста (что относительно медленно) может считывать 90 МБ / с с приличным процессором / жестким диском.Вы можете сделать это намного быстрее с помощью файлов, отображаемых в памяти, но если ваш дисковод не сможет с этим справиться, это не будет иметь большого значения.

Есть вещи, которые вы можете сделать, чтобы улучшить производительность ввода-вывода, но вы быстро обнаружите, чтоЧтобы ускорить ввод-вывод, нужно улучшить аппаратное обеспечение.

Если вы используете жесткий диск, который может поддерживать скорость чтения 100 МБ / с и 120 операций ввода-вывода в секунду, вы ограничены этими факторами и замените диск наSSD с 500 МБ / с и 80 000 IOPS будет работать быстрее.

Аналогично, если вы используете сеть со скоростью 100 МБ / с, вы можете получить только 12 МБ / с при скорости 1 Гбит / с.В сети вы можете получить 110 МБ / с, а в сети 10 Гбит / с вам может повезти - 1 ГБ / с.

5 голосов
/ 15 октября 2011

Если вы выполняете много крошечных операций ввода-вывода, то объединение их в одну большую операцию ввода-вывода может значительно ускорить ваш код. Методы функционального программирования, как правило, облегчают написание операций сбора и преобразования данных (например, вы можете хранить элементы для ожидающего вывода в списке и использовать карту для применения к ним преобразователя элемент-в-текст или элемент-в-двоичный код). В противном случае, нет, функциональные методы программирования не преодолевают медленные каналы. Если необработанная скорость ввода-вывода ограничивает, в Java и в других местах, и у вас достаточно аппаратных потоков, у вас должен быть один поток с высоким приоритетом для каждого независимого канала ввода-вывода, и он должен выполнять только ввод-вывод (без преобразования данных, ничего такого). Это увеличит вашу скорость ввода-вывода, и тогда вы сможете использовать другие потоки для выполнения преобразований, бизнес-логики и тому подобного.

2 голосов
/ 15 октября 2011

Один вопрос - есть ли у вас неограниченное время для разработки вашего приложения или нет.Если у вас неограниченное время, то программы Java и Scala будут иметь одинаковую производительность, поскольку вы можете писать программы Scala, которые будут генерировать точно такой же байт-код, что и Java.

Но если у вас есть неограниченное время, почему бы и нетразрабатывать в C (или ассемблере)?Вы получите лучшую производительность.

Другой - насколько сложен ваш код ввода-вывода.Если это что-то довольно тривиальное, то Scala, вероятно, не принесет особой пользы, так как «мяса» недостаточно для использования его возможностей.

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

Например, параллельное выполнение вычисления для набора данных выполняется в Java с помощью ForkJoinPool, который необходимо создать, затем создать класс, обертывающий вычисления, разбить его для каждого элемента и отправить в пул,

В Scala: collection.par.map(calculation).Написание этого намного быстрее, чем Java, так что вы просто делаете это и имеете свободное время для решения других вопросов.

Из личного опыта у меня есть связанная история.Я читал в статье в блоге, что BuildR, инструмент сборки на основе ruby, был в два раза быстрее, чем Maven для простой сборки.Учитывая, что Ruby примерно в 20 раз медленнее, чем Java, я был удивлен.Итак, я профилировал Maven.Оказалось, что он примерно 1000 раз проанализировал один и тот же XML-файл.Теперь, конечно, с осторожным дизайном, они могли бы сократить это до одного раза.Но я предполагаю, что причина, по которой они этого не сделали, заключается в том, что прямой подход в Java привел к тому, что дизайн стал более сложным, чтобы измениться после него.С BuildR дизайн стал проще, а производительность лучше.В Scala вы чувствуете, что программирование на динамическом языке все еще находится на одном уровне с Java с точки зрения производительности.

ОБНОВЛЕНИЕ: Если подумать об этом, в Scala есть некоторые области, которые дают большую производительность, чемJava (опять же, если предположить, что узкое место ввода-вывода связано с кодом, который оборачивает операции ввода-вывода, а не с чтением / записью байтов): * Ленивые аргументы и значения - могут подтолкнуть затраты циклов ЦП к тому моменту, когда они действительно требуются * Специализация - позволяетпопросите компилятор создавать копии общих структур данных для собственных типов, избегая, таким образом, упаковки, распаковки и приведения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...