Я просто хотел указать, что GNU uniq
кажется ужасно медленным, даже в отсортированном списке.
Я просто попытался получить список префиксов каталогов из списка отсортированных имен файлов:
$ pv all_files | cut -d '/' -f 1,2,3,4 | uniq > all_prefixes
36.7GiB 0:07:41 [81.4MiB/s]
$ pv all_files | cut -d '/' -f 1,2,3,4 | sort -u > all_prefixes2
36.7GiB 0:03:14 [ 193MiB/s]
$ pv all_files | cut -d '/' -f 1,2,3,4 | awk '!x[$0]++' > all_prefixes3
36.7GiB 0:02:18 [ 270MiB/s]
sort -u кажется в два раза быстрее, чем uniq, и это при чтении сортировки из stdin и записи в stdout, поэтому я пока не вижу, чтобы это делало распараллеливание. Я понятия не имею, почему uniq должен быть намного медленнее, чем сортировать, поскольку он не должен сортировать список ...
Результат этой команды очень мал (есть много дубликатов), только 264 КБ и сортировка завершается сразу после выполнения pv.
Те же скорости остаются, если вы меняете порядок команд, мой поток ограничен здесь временем процессора, а не доступом к диску и кешами (у меня только 8 ГБ ОЗУ, и мой подкачка не используется)
Я запускаю это на машине fedora 31 с GNU Coreutils и UniQ и GNU AWK; локаль установлена в en_US.UTF-8
ОБНОВЛЕНИЕ , так как это немного заинтриговало меня, я сделал еще несколько тестов, давайте разберем вырезанную часть и убедимся, что файл хорошо отсортирован
cat all_files | cut -d '/' -f 1,2,3,4 | sort -T . > test
Это займет 8,4 минуты. тест теперь 7,9 ГБ большой
давайте запустим эти инструменты в файле, а не в конвейере, это позволит этим инструментам выполнить дополнительную оптимизацию, например, sort будет multi thread. а также от более быстрого ssd.
Вы можете не заметить, что сортировка также занимает много памяти, так как она делает хитрые трюки с временными файлами в / tmp, которые могут быть tmpfs и будут у вас в памяти (попробуйте отсортировать файл больше, чем / tmp, вы попадете в пространство вопросы, поэтому мне нужен флаг -T. в приведенной выше команде)
$ time sort -u test > /dev/null
339.24user 3.54system 1:28.87elapsed 385%CPU (0avgtext+0avgdata 2365856maxresident)k
9555544inputs+0outputs (0major+591298minor)pagefaults 0swaps
$ time awk '!x[$0]++' test > /dev/null
51.15user 1.55system 0:52.94elapsed 99%CPU (0avgtext+0avgdata 10976maxresident)k
0inputs+0outputs (0major+1923minor)pagefaults 0swaps
$ time uniq test > /dev/null
421.89user 2.76system 7:06.63elapsed 99%CPU (0avgtext+0avgdata 1980maxresident)k
52712inputs+0outputs (0major+79minor)pagefaults 0swaps
Так что, похоже, ваше awk-решение является самым быстрым из этих 3 , и на самом деле использует меньше всего памяти
update2
и теперь с более простым языком
$ export LC_ALL=c
$ time sort -u test > /dev/null 1.2m ? Tue Apr 21 17:09:22 2020
119.18user 3.64system 0:38.24elapsed 321%CPU (0avgtext+0avgdata 2013472maxresident)k
$ time awk '!x[$0]++' test > /dev/null 1161ms ? Tue Apr 21 17:07:31 2020
67.23user 2.50system 1:10.16elapsed 99%CPU (0avgtext+0avgdata 10480maxresident)k
7187520inputs+0outputs (0major+1912minor)pagefaults 0swaps
$ time uniq test > /dev/null
22.05user 2.02system 0:24.24elapsed 99%CPU (0avgtext+0avgdata 1488maxresident)k
2959648inputs+0outputs (1major+72minor)pagefaults 0swaps
На этот раз uniq действительно выигрывает гонку ... как намекает Стефан Шазелас в комментариях, установка вашего языка на C делает сортировку и uniq целой кучей быстрее!
time
?