Zastanawiałem się, czy istnieją ogólne wytyczne dotyczące optymalizacji skryptów Bash.
Na przykład wygodniej jest pisać pętle niż wiersze poleceń, ale czy jest też szybsze przetwarzanie w systemie? Przykład:
for i in a b c; do echo $i; done echo a echo b echo c
Czasami ludzie przedstawiają różne rozwiązania tego samego problemu. Na przykład
sed
,cut
,awk
, iecho
są w stanie rozebrać się z ciągu cyfr. Zastanawiałem się, czy możesz powiedzieć, że im mniej cyfr ma kod, tym szybciej jest, jeśli używasz:to samo polecenie, np
STRING=abc.def echo ${STRING} | sed 's/.def//g' echo ${STRING} | sed '$s/....$//'
różne polecenia, np
STRING=abc.def echo ${STRING} | cut -d . -f 1 echo ${STRING} | sed 's/.def//g'
shell-script
Vincent
źródło
źródło
Odpowiedzi:
Powłoki nie przeprowadzają żadnej reorganizacji otrzymanego kodu, jest on po prostu interpretowany jeden wiersz po drugim (nic innego nie ma większego sensu w interpretatorze poleceń). Większość czasu spędzanego przez powłokę przeznacza się na analizę leksykalną / parsowanie / uruchamianie programów o nazwie.
W przypadku prostych operacji (takich jak ciąg znaków w przykładach na końcu pytania) zdziwiłbym się, gdyby czas załadowania programów nie spowodował żadnych drobnych różnic prędkości.
Morał tej historii jest taki, że jeśli naprawdę potrzebujesz większej prędkości, lepiej jest skorzystać z (częściowo) skompilowanego języka, takiego jak Perl lub Python, który jest szybszy od samego początku, w którym możesz napisać wiele operacji wymienionych bezpośrednio i nie trzeba wywoływać zewnętrznych programów, i ma opcję wywoływania zewnętrznych programów lub wywoływania zoptymalizowanych modułów C (lub cokolwiek innego), aby wykonać większą część pracy. To jest powód, dla którego w Fedorze „cukier do administrowania systemem” (GUI) jest napisany w Pythonie: można dodać fajny GUI bez większego wysiłku, wystarczająco szybki dla takich aplikacji, mieć bezpośredni dostęp do wywołań systemowych. Jeśli to za mało, wybierz C ++ lub C.
Ale nie idź tam, chyba że możesz udowodnić, że wzrost wydajności jest wart utraty elastyczności i czasu rozwoju. Skrypty powłoki nie są takie złe, aby je odczytać, ale wzdrygam się, gdy pamiętam niektóre skrypty użyte do instalacji Ultrix, które kiedyś próbowałem rozszyfrować. Zrezygnowałem, zastosowano zbyt wiele „optymalizacji skryptu powłoki”.
źródło
Pierwszą zasadą optymalizacji jest: nie optymalizuj . Najpierw przetestuj. Jeśli testy wykażą, że twój program działa zbyt wolno, poszukaj możliwych optymalizacji.
Jedynym sposobem, aby się upewnić, jest przeprowadzenie testu porównawczego dla swojego przypadku użycia. Istnieje kilka ogólnych zasad, ale dotyczą one tylko typowych ilości danych w typowych aplikacjach.
Niektóre ogólne zasady, które mogą, ale nie muszą być prawdziwe, w konkretnych okolicznościach:
echo $foo
jest wolniejszy niżecho "$foo"
, ponieważ bez podwójnych cudzysłowów dzieli się$foo
na słowa i interpretuje każde słowo jako wzorzec wieloznaczny nazwy pliku. Co ważniejsze, zachowanie dzielenia i globowania jest rzadko pożądane. Pamiętaj więc, aby zawsze umieszczać podwójne cudzysłowy wokół podstawień zmiennych i podstawień poleceń:"$foo"
,"$(foo)"
.cut
lubhead
mogą być emulowanesed
, alesed
będą wolniejsze iawk
będą jeszcze wolniejsze. Przetwarzanie ciągów powłoki jest powolne, ale w przypadku krótkich ciągów znacznie przewyższa wywoływanie programu zewnętrznego.Rzadko zdarza się, że wydajność jest problemem w skryptach powłoki. Powyższa lista ma charakter wyłącznie orientacyjny; w większości przypadków doskonale jest stosować metody „powolne”, ponieważ różnica często wynosi ułamek procenta.
Zwykle celem skryptu powłoki jest szybkie wykonanie zadania. Musisz wiele zyskać na optymalizacji, aby usprawiedliwić spędzanie dodatkowych minut na pisaniu scenariusza.
źródło
python
iruby
są zdecydowanie wolniejsze, przynajmniej w moim systemie, uruchamianieperl
jest tak szybkie, jakbash
lubksh
. GNU awk jest znacznie wolniejszy niż GNU sed, szczególnie w lokalizacjach utf-8, ale nie dotyczy to wszystkich awks i wszystkich plików. ksh93> myślnik> pdksh> zsh> bash nie zawsze są tak wyraźne. Niektóre pociski są lepsze w niektórych rzeczach niż inne, a zwycięzca nie zawsze jest taki sam.Skradzione z typowych błędów skryptu powłoki autorstwa Pádraiga Brady'ego.
źródło
for i in *; do wc -l "$i">/dev/null; done
lepiejfor i in *; do wc -l "$i"; done>/dev/null
.time
cmdwc -l
, sprawdź, czy zaktualizowałem po opublikowaniu danych wyjściowych