Я понимаю, что и Java, и Perl очень стараются найти универсальный размер буфера по умолчанию при чтении файлов, но я считаю, что их выбор все более устарел, и у меня возникла проблема с изменением выбора по умолчанию, когда дело доходит до Perl.
В случае Perl, который, как мне кажется, по умолчанию использует буферы 8K, аналогичные буферам в Java выбор, я не могу найти ссылку с помощью поисковой системы веб-сайта perldoc (на самом деле Google) о том, как увеличить размер входного буфера файла по умолчанию, скажем, 64 КБ.
Из приведенной выше ссылки, чтобы показать, как буферы 8K не масштабируются:
Если в каждой строке обычно около 60 символов, то в файле из 10 000 строк содержится около 610 000 символов. Построчное чтение файла с буферизацией требует только 75 системных вызовов и 75 ожиданий диска вместо 10 001.
Таким образом, для файла размером 50 000 000 строк с 60 символами в строке (включая новую строку в конце) с буфером 8 КБ он сделает 366211 системных вызовов для чтения файла 2,8 ГБ. Кроме того, вы можете подтвердить это поведение, посмотрев на дельту чтения ввода-вывода диска (по крайней мере, в Windows верхняя часть * nix показывает то же самое, я уверен) в списке процессов диспетчера задач в качестве вашей программы Perl чтение в текстовом файле занимает 10 минут :)
Кто-то задал вопрос об увеличении размера входного буфера Perl на perlmonks, кто-то ответил здесь, что вы может увеличить размер «$ /» и, таким образом, увеличить размер буфера, однако из perldoc:
Установка $ / для ссылки на целое число, скаляр, содержащий целое число, или скаляр, который может быть преобразован в целое число, будет пытаться читать записи вместо строк, при этом максимальный размер записи является целым числом, на которое указывает ссылка.
Поэтому я предполагаю, что это на самом деле не увеличивает размер буфера, который Perl использует для упреждающего чтения с диска при использовании типичного:
while(<>) {
#do something with $_ here
...
}
идиома «построчно».
Теперь могло случиться так, что другая версия приведенного выше кода "считывала запись за раз, а затем разбирала ее на строки" была бы быстрее в целом и обошла бы основную проблему со стандартной идиомой и не могла бы изменить буфер по умолчанию. size (если это действительно невозможно), потому что вы можете установить «размер записи» на все, что захотите, а затем разобрать каждую запись на отдельные строки и надеяться, что Perl поступит правильно и в конечном итоге сделает один системный вызов для каждой записи, но это добавляет сложности, и все, что я действительно хочу сделать, это получить легкий прирост производительности, увеличив буфер, используемый в приведенном выше примере, до достаточно большого размера, скажем 64 КБ, или даже настроив этот размер буфера до оптимального. размер для длительного чтения с использованием тестового сценария в моей системе без лишних хлопот.
В Java дела обстоят намного лучше в том, что касается прямой поддержки увеличения размера буфера.
В Java я считаю, что текущий размер буфера по умолчанию, который использует java.io.BufferedReader, также составляет 8192 байта, хотя современные ссылки в документах JDK двусмысленны, например, в документах 1.5 говорится только:
Может быть указан размер буфера или может быть принят размер по умолчанию. Значение по умолчанию достаточно велико для большинства целей.
К счастью, с Java вам не нужно доверять разработчикам JDK, которые приняли правильное решение для вашего приложения и могут установить свой собственный размер буфера (64 КБ в этом примере):
import java.io.BufferedReader;
[...]
reader = new BufferedReader(new InputStreamReader(fileInputStream, "UTF-8"), 65536);
[...]
while (true) {
String line = reader.readLine();
if (line == null) {
break;
}
/* do something with the line here */
foo(line);
}
Производительность настолько велика, что вы можете выжать из синтаксического анализа по одной строке за раз, даже с огромным буфером и современным оборудованием, и я уверен, что есть способы получить максимальную производительность от чтения в файле, читая большие многострочные записи и разбиение каждой на токены, а затем выполнение работы с этими токенами один раз для каждой записи, но они добавляют сложность и крайние случаи (хотя, если есть элегантное решение на чистой Java (только с использованием функций, присутствующих в JDK 1.5), это было бы круто знать о). Увеличение размера буфера в Perl решило бы, по крайней мере, 80% проблемы производительности для Perl, сохраняя при этом простоту.
У меня вопрос:
Есть ли способ отрегулировать этот размер буфера в Perl для вышеупомянутой типичной идиомы «построчно», подобно тому, как размер буфера был увеличен в примере Java?