Je voulais juste souligner que le gnu uniq
semble terriblement lent, même sur une liste triée.
J'ai juste essayé d'obtenir une liste de préfixes de répertoire à partir d'une liste de noms de fichiers triés:
$ 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 semble deux fois plus rapide que uniq, et c'est avec la lecture de tri depuis stdin et l'écriture vers stdout, donc je ne le vois pas encore faire de parallélisation. Je ne sais pas pourquoi uniq devrait être tellement plus lent que le tri, car il n'a pas à trier la liste ...
La sortie de cette commande est très petite (il y a beaucoup de doublons), seulement 264 ko et le tri se termine instantanément après que pv soit fait.
Les mêmes vitesses restent si vous inversez l'ordre des commandes, mon flux est limité par le temps de processeur ici, pas l'accès au disque et les caches (je n'ai que 8 Go de RAM et mon swap n'est pas utilisé)
J'exécute ceci sur une machine fedora 31 avec gnu coreutils sort et uniq et gnu awk; les paramètres régionaux sont définis sur en_US.UTF-8
MISE À JOUR , étant donné que cela m'a un peu intrigué, j'ai fait d'autres tests, supprimons la partie coupée et assurez-vous que le fichier est bien trié
cat all_files | cut -d '/' -f 1,2,3,4 | sort -T . > test
Cela prend 8,4 minutes. le test fait maintenant 7,9 Go
exécutons ces outils sur le fichier plutôt que dans un tube, cela permettra à ces outils de faire un peu plus d'optimisation, comme le tri sera multi-thread. et aussi d'un ssd plus rapide.
Vous ne remarquerez peut-être pas que le tri prend également beaucoup de mémoire, car il fait des astuces intelligentes avec les fichiers temporaires dans / tmp qui pourraient être tmpfs et seront dans votre RAM (essayez de trier un fichier plus grand que / tmp, vous courrez dans l'espace problèmes, c'est pourquoi j'ai besoin du drapeau -T. dans la commande ci-dessus)
$ 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
Il semble donc que votre solution awk soit la plus rapide de ces 3 et utilise en fait le moins de mémoire
update2
et maintenant avec une locale plus simple
$ 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
Cette fois, uniq gagne la course ... comme le laisse entendre Stéphane Chazelas dans les commentaires, définir votre locale sur C accélère le tri et uniq tout un tas!
time
?