Potrzebujesz sugestii ekspertów dotyczących poniższego porównania:
Segment kodu za pomocą pętli:
for file in `cat large_file_list`
do
gzip -d $file
done
Segment kodu za pomocą prostego rozszerzenia:
gzip -d `cat large_file_list`
Który będzie szybszy? Muszę manipulować dużym zestawem danych.
linux
bash
shell-script
shell
Leon
źródło
źródło
gzip
systemu, liczby plików na liście plików i wielkości tych plików.xargs gzip -d < large_file_list
ale uważaj na spacje w nazwach plików, być może ztr \\n \\0 large_file_list | xargs -0 gzip -d
Odpowiedzi:
Powikłania
Następujące działania będą działać tylko czasami:
Trzy problemy (w
bash
większości innych powłok podobnych do Bourne'a):Nie powiedzie się, jeśli w nazwie pliku znajduje się spacja lub znaki nowego wiersza (zakładając,
$IFS
że nie został zmodyfikowany). Wynika to z podziału słów powłoki .Może również zawieść, jeśli nazwa pliku zawiera znaki glob-active. Wynika to z faktu, że powłoka zastosuje rozszerzenie nazwy ścieżki do listy plików.
Nie powiedzie się również, jeśli nazwa pliku zaczyna się od
-
(jeśliPOSIXLY_CORRECT=1
dotyczy to tylko pierwszego pliku) lub jeśli jest nim jakakolwiek nazwa pliku-
.Nie powiedzie się również, jeśli będzie w nim zbyt wiele nazw plików, aby zmieściły się w jednym wierszu poleceń.
Poniższy kod podlega takim samym problemom jak powyższy kod (z wyjątkiem czwartego)
Niezawodne rozwiązanie
Jeśli masz
large_file_list
dokładnie jedną nazwę pliku w wierszu, a nazwanego pliku-
nie ma wśród nich, a jesteś w systemie GNU, użyj:-d'\n'
każexargs
traktować każdy wiersz danych wejściowych jako osobną nazwę pliku.-r
mówi,xargs
aby nie uruchamiać polecenia, jeśli plik wejściowy jest pusty.--
mówi,gzip
że następujących argumentów nie należy traktować jako opcji, nawet jeśli zaczynają się od-
.-
sam nadal byłby jednak traktowany jako-
zamiast wywoływanego pliku-
.xargs
umieści wiele nazw plików w każdym wierszu poleceń, ale nie tyle, że przekroczy limit wiersza poleceń. Zmniejsza to liczbę uruchomieńgzip
procesu i dlatego jest tak szybkie. Jest również bezpieczny: nazwy plików będą również chronione przed dzieleniem słów i rozszerzaniem nazw ścieżek .źródło
for
Pętla będzie - jak dotąd - najwolniejsza. Pozostałe dwie metody będą bardzo blisko siebie.xargs
: przynajmniej wersja GNU ma--arg-file
opcję (krótka forma-a
). Możnaxargs -a large_file_list -rd'\n' gzip -d
zamiast tego zrobić . Skutecznie, nie ma żadnej różnicy, poza tym, że<
jest operator powłoki i pozwoliłobyxargs
czytać ze standardowego wejścia (które shell „linki” do pliku), a-a
stałabyxargs
wyraźnie otworzyć plik w pytaniuparallel
do uruchamiania wielu kopiigzip
, alexargs
(przynajmniej GNU) również ma-P
przełącznik do tego. Na maszynach wielordzeniowych może to mieć znaczenie. Ale możliwe jest również, że i tak dekompresja jest całkowicie związana z operacjami wejścia / wyjścia.Wątpię, żeby to miało znaczenie.
Użyłbym pętli tylko dlatego, że nie wiem, ile plików znajduje się na liście plików, i nie wiem (ogólnie), czy w nazwach plików znajdują się spacje. Wykonanie podstawienia polecenia, które wygenerowałoby bardzo długą listę argumentów, może spowodować błąd „Zbyt długa lista argumentów”, gdy wygenerowana lista jest zbyt długa.
Moja pętla wyglądałaby
To dodatkowo pozwoliłoby mi wstawiać polecenia do przetwarzania danych po
gunzip
poleceniu. W rzeczywistości, w zależności od tego, jakie są dane i co należy z nimi zrobić, może być nawet możliwe ich przetwarzanie bez zapisywania go w pliku:(gdzie
process_data
jest jakiś potok odczytujący nieskompresowane dane ze standardowego wejścia)Jeśli przetwarzanie danych trwa dłużej niż jego rozpakowanie, pytanie, czy pętla jest bardziej wydajna, czy nie, staje się nieistotne.
Idealnie wolałbym jednak nie wyłączać listy nazw plików i zamiast tego używać wzorca globowania nazw plików, jak w
gdzie
./*.gz
jest jakiś wzór pasujący do odpowiednich plików. W ten sposób nie jesteśmy zależni od liczby plików ani od znaków używanych w nazwach plików (mogą zawierać znaki nowej linii lub inne białe znaki, lub zaczynać od myślników itp.)Związane z:
źródło
Z tych dwóch, ten z wszystkimi plikami przekazanymi do pojedynczego wywołania
gzip
prawdopodobnie będzie szybszy, właśnie dlatego, że wystarczy uruchomićgzip
tylko raz. (To znaczy, jeśli polecenie w ogóle działa, zobacz inne odpowiedzi na zastrzeżenia).Chciałbym jednak przypomnieć o złotej zasadzie optymalizacji : nie rób tego przedwcześnie.
Nie optymalizuj tego typu rzeczy, zanim zorientujesz się, że to problem.
Czy ta część programu zajmuje dużo czasu? Cóż, dekompresowanie dużych plików może i i tak będziesz musiał to zrobić, więc odpowiedź może nie być tak łatwa.
Pomiar. Naprawdę, to najlepszy sposób, aby się upewnić.
Zobaczysz wyniki na własne oczy (lub własny stoper) i będą one dotyczyć Twojej sytuacji, której losowe odpowiedzi w Internecie mogą nie mieć. Umieść oba warianty w skryptach i uruchom
time script1.sh
, oraztime script2.sh
. (Zrób to z listą pustych skompresowanych plików, aby zmierzyć bezwzględną kwotę narzutu).źródło
Jak szybki jest twój dysk?
To powinno wykorzystać wszystkie twoje procesory:
Zatem twoim ograniczeniem będzie prawdopodobnie prędkość twojego dysku.
Możesz spróbować dostosować za pomocą
-j
:Spowoduje to uruchomienie połowy zadań równolegle do poprzedniego polecenia i zmniejszy obciążenie dysku, więc w zależności od dysku może to być szybsze.
źródło