Java AsynchronousFileChannel с большим количеством обработчиков открытых файлов в Linux

#java #linux

#java #linux

Вопрос:

Мое понимание асинхронного ввода-вывода файлов может быть неправильным, но я пытаюсь использовать последнюю версию AsynchronousFileChannel JDK 7 для ускорения работы приложения с неожиданным худшим результатом. Приложение использовало режим синхронизации с PrintWriter до того, как я внес изменения, как показано ниже:

     if( asynchMode ){
        AsynchronousFileChannel writer = AsynchronousFileChannel.open(Paths.get(outputFileName),
        StandardOpenOption.WRITE, StandardOpenOption.CREATE);       
        ((AsynchronousFileChannel)writer).write(ByteBuffer.wrap(builder.toString().getBytes()), 0);
    else{
        PrintWriter writer = null;
        try{
            writer = new PrintWriter(new BufferedWriter(new FileWriter(
            outputFileName)));
            ((PrintWriter)writer).write(builder.toString());
        }
        finally{
            if( null!=writer )
                writer.close();
        }
    }
  

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

Одна странная вещь, помимо более низкой производительности, заключается в том, что при выполнении a появляется много файловых дескрипторов ls -l /proc/p . Спасибо за любые разъяснения и помощь!

Ответ №1:

В первом примере вы не закрываете файл, во втором случае вы это делаете.

Я бы убедился, что вы тестируете только то, что вас интересует. В противном случае причиной задержки может быть добавление getByte(), которое вы выполняете только в первом случае. Я предлагаю вам начать с byte[] перед запуском таймера в обоих случаях для сравнения like, for like.

Примечание: если у вас есть один блок данных / текста с использованием буферизованного потока / записи, это в лучшем случае только добавит накладных расходов.

Когда дело доходит до записи реальных файлов, это запись данных на диск, которая является бутылочным горлышком. Ваша система может копировать данные со скоростью много ГБ / с, но большинство вращающихся дисков могут поддерживать скорость записи только 50-100 МБ / с. Поэтому повышение эффективности в Java может не дать вам желаемых результатов.

Комментарии:

1. На самом деле, я предполагаю, что мои ожидания от асинхронного файлового ввода-вывода JDK 7, возможно, нереалистичны. Если вы посмотрите на мой код выше, вы можете увидеть, что никакие обработчики не были переданы, а экземпляр asynch file channel сразу выходит за рамки после оператора if. Я не использовал метод close(), потому что понимаю, что файлы не были записаны полностью или вообще не были записаны, если я вызываю метод close() сразу после метода write(…) . Однако, похоже, что все асинхронные файловые каналы (и базовые файловые дескрипторы в Linux) не закрываются до выхода JVM.

2. К сожалению, это потенциальная бомба замедленного действия, поскольку может быть открыто много, много FD, и каждый FD может содержать огромный буфер содержимого, в результате чего приложение Java задерживает много ненужных ресурсов. Мое первоначальное ожидание состояло в том, что GC позаботится об удалении экземпляров файлового канала, а также базовых FDS путем удаления содержимого файла и закрытия FDs. Думаю, для меня все вернулось на круги своя, т.Е. асинхронный ввод-вывод файлов бесполезен для моего сценария. Спасибо.