#performance #perl
#Производительность #perl
Вопрос:
Я обнаружил, что следующий код perl выполняется с удивительно разной скоростью, иногда быстро, иногда очень медленно. У меня есть несколько папок, содержащих десятки тысяч файлов, через которые мне нужно запустить этот код. Я запускаю это на cygwin с Windows 7. Просто интересно, может ли кто-нибудь помочь мне ускорить его или, по крайней мере, выяснить, почему скорость меняется. Во всех этих ситуациях моего процессора и памяти должно быть достаточно.
внешний цикл для перебора списка $ dir
opendir(DIR, $dir);
@all=readdir(DIR);
@files = (0..$#all);
$i=-1;
foreach $current (@all){
if (-f "$dir/$current") {
$files[ $i]=$current;
}
}
push @Allfiles,@files[0..$i];
closedir(DIR);
Комментарии:
1. Делаете ли вы что-нибудь еще на своем компьютере одновременно, например, запускаете bittorrent или игровой сервер или что-то подобное?
Ответ №1:
Вероятно, вы связаны с вводом-выводом, поэтому изменения в вашем коде, вероятно, не повлияют на общее время выполнения — время выполнения будет зависеть от того, находятся ли записи каталога в кэше или нет.
Но ваш код использует временные массивы без уважительной причины, используя слишком много оперативной памяти, если каталоги очень большие. Вы могли бы упростить его до:
opendir(DIR, $dir);
while (my file = readdir(DIR)) {
push @Allfiles, $file if (-f "$dir/$file");
}
closedir(DIR);
Нет временных массивов.
Комментарии:
1. Если операционная система сильно ограничена памятью, эти временные массивы могут быть заменены на диск, что значительно замедляет работу (и по иронии судьбы).
2. Не думал об этом — должны быть действительно большие каталоги или очень ограниченная память. В этом случае удаление временных файлов немного помогло бы, но
@Allfiles
само по себе может стать слишком большим в этих обстоятельствах… Я думаю, в этом случае нет реального решения, кроме как разбить работу.3. На самом деле вам нужно присвоить значение $ _ в условии while(), поскольку readdir() не является особым случаем, который помещает материал в $ _ для вас.
4. @tadmc: Я проверил это перед публикацией, и это сработало (perl 5.12, я думаю). Но на самом деле это не так с perl 5.8, который у меня здесь … или, может быть, я тогда не выпил достаточно кофе и вообразил все это:-/ Исправлено, спасибо.
5. Изначально я пробовал именно этот код. Это было довольно медленно. Тогда я подумал, что, возможно, нажатие списка замедлило работу. Поэтому я попытался сначала выделить достаточно длинный массив. Итак, по вашему мнению, нажатие или сдвиг списка, если на то пошло, не должны быть причиной низкой скорости?
Ответ №2:
Если при первом запуске он медленный, а после этого быстрый, то проблема в том, что ваша система кэширует чтения. При первом запуске кода данные должны быть считаны с вашего диска. После этого данные все еще кэшируются в оперативной памяти. Если вы будете ждать достаточно долго, кэш очистится, и вам придется снова обращаться к дискам.
Или иногда вы можете одновременно выполнять какую-то другую задачу с интенсивным использованием диска, но не в другое время, когда вы запускаете свой код.
Комментарии:
1. Это происходит медленно в первый раз, и в некоторые другие не первые разы тоже. У меня 8 ГБ памяти, разве этого недостаточно для хранения файлов в кэше? Кстати, я не выполнял другие задачи с интенсивным использованием диска одновременно, когда наблюдал это.
2. Используете ли вы что-нибудь, требующее много памяти, например, Firefox с множеством вкладок, заполненных видео? 8 ГБ должно быть более чем достаточно, если только каталог, который вы перечисляете, не заполнен крошечными (менее 4k) файлами.
3. нет, совсем нет с этими задачами, требующими много памяти. вот почему мне было очень любопытно узнать, в чем разница между запусками.