Некоторые быстрые идеи;
find
sort
С этими двумя кусками, и если диапазон дат известен, вы можете использовать простой глобус с именем файла вместо awk. Например (предположим, что ваша оболочка - bash
):
Все файлы одного дня
echo xml_20140207_*.zip | xargs -n 1 -P 10 zipgrep "my search string"
Файлы, созданные между 15:00 и 18:00, либо в 07 или 10 февраля 2014:
echo xml_201402{07,10}_1{5. .7}*.zip | xargs -n 1 -P 10 zipgrep "my search string"
Есть часть, которую можно легко улучшить, но это не самая медленная часть.
find / home / mydir / -type f | сортировать | \ awk "/xml_20140207_000016.zip/,/xml_20140207_235938.zip/"
Это несколько расточительно, потому что сначала перечисляются все файлы, затем сортируются имена файлов и извлекаются наиболее интересные. Команда find
должна быть завершена до начала сортировки.
Было бы быстрее перечислить в первую очередь только интересные файлы или, по крайней мере, как можно меньший надмножество. Если вам нужен более мелкозернистый фильтр по именам, чем может find
, переходите в awk, но не сортируйте: awk и другие построчные фильтры могут обрабатывать строки одну за другой, но сортировка требует полный ввод.
find /home/mydir/ -name 'xml_20140207_??????.zip' -type f | \
awk 'match($0, /_[0-9]*.zip$/) &&
(time = substr($0, RSTART+1, RLENGTH-5)) &&
time >= 16 && time <= 235938' |
xargs -n 1 -P 10 zipgrep "my search string"
Наиболее явно неоптимальной является zipgrep. Здесь нет простого способа повысить производительность из-за ограничений программирования оболочки. Сценарий zipgrep работает, перечисляя имена файлов в архиве и вызывая grep
для каждого содержимого файла, один за другим. Это означает, что zip-архив снова и снова анализируется для каждого файла. Программа Java (или Perl, или Python, или Ruby и т. Д.) Может избежать этого, обработав файл только один раз.
Если вы хотите придерживаться программирования оболочки, вы можете попробовать смонтировать каждый zip вместо использования zipgrep.
… | xargs -n1 -P2 sh -c '
mkdir "mnt$$-$1";
fuse-zip "$1" "mnt$$-$1";
grep -R "$0" "mnt$$-$1"
fusermount -u "mnt$$-$1"
' "my search string"
Обратите внимание, что параллелизм вам не очень поможет: ограничивающим фактором при большинстве настроек будет пропускная способность дискового ввода-вывода, а не время процессора.
Я ничего не тестировал, но думаю, что лучше всего можно было бы улучшить реализацию zipgrep на более мощном языке.
Неясно, где находится ваше узкое место. Давайте предположим, что это в чтении файлов. В зависимости от вашей системы хранения, это быстрее прочитать весь файл перед его обработкой. Это особенно верно для Zipgrep
, который делает несколько ищет в файле: если файл не полностью в памяти, вы ждете, что диск для поиска.
find ... | parallel -j1 'cat {} >/dev/null; echo {}' | parallel zipgrep "my search string"
Приведенная выше будет CAT
CAT
один файл за раз и тем самым положить его в кэш памяти, затем запустить один Zipgrep
на CPU, который затем прочитал из кеша памяти.
Я использовал RAID Systems, в которых вы получили 6x скорость, чтение 10 файлов параллельно, чем считывание 1 файла за раз или считывание 30 файлов параллельно. Если бы мне пришлось бежать выше на эту систему RAID, я бы отрегулировал -J1
- 1 -J10
.
Используя GNU Parallel вместо xargs
, вы охраняете себя от смешивания вывода (см. http://www.gnu.org/software/parallel/man.html#differences-betwen -xargs-and-gnu-параллель ).