Różnica w wydajności między argumentem stdin a wierszem poleceń

11

W przypadku niektórych poleceń można podać określone dane wejściowe jako argument stdin lub wiersz poleceń.

W szczególności załóżmy, że commandmożemy przyjąć wejście standardowe i nazwę pliku jako argument wiersza poleceń, i command < myfile, cat myfile | command i command myfilemoże dać ten sam wynik.

Na przykład,

Gdy polecenie brzmi sed:

sed s/day/night/ <myfile >new   
sed s/day/night/ myfile >new    
cat myfile | sed s/day/night/ >new

Gdy polecenie brzmi cat:

cat < myfile
cat myfile
  1. Zastanawiałem się, czy istnieją jakieś ogólne zasady dotyczące ich występów, tj. Która z nich jest zwykle najbardziej wydajna, a która najmniej?
  2. Czy przekierowanie jest zawsze lepsze niż potok?
Tim
źródło
1
Życzę wszystkim, aby zadawali te (zduplikowane) pytania i pisali od podstaw swoją własną powłokę jako ćwiczenie.
alex
1
proszę nie używać „Dzięki!” w twoich pytaniach. Głosuj na odpowiedzi, aby wyrazić swoją wdzięczność.
alex
@Alex: Jeśli to duplikat, prosimy o link do duplikatu, a my zajmiemy się jego zamknięciem. Zazwyczaj nie odpowiadasz na pytanie, o którym wiesz, że jest duplikatem, i oflagujesz je, by zwrócić uwagę moderatora.
Caleb
1
@alex: Gdzie mogę nauczyć się pisać własną powłokę?
Tim
@Caleb: Jestem pewien, że w ciągu ostatniego miesiąca zadawano to pytanie 2 lub 3 razy, po prostu nie mam przydatnego linku :-p
alex

Odpowiedzi:

6

cat file | commandSkładnia jest uważany za Useless użycieCat . Ze wszystkich opcji wymaga wydajności, ponieważ musi odrodzić inny proces w jądrze. Jakkolwiek nieistotne może się to okazać na dużym obrazie, jest to narzut, którego nie mają inne formy. Zostało to omówione na pytania takie jak: Czy powinienem dbać o niepotrzebne koty?

Między pozostałymi dwiema postaciami praktycznie nie ma różnic w wydajności. STDIN to specjalny węzeł pliku, który proces musi otwierać i czytać tak jak każdy inny. Przekazanie nazwy pliku zamiast STDIN powoduje po prostu otwarcie innego pliku.

Różnica polegałaby na tym, jakich funkcji / elastyczności szukasz.

  • Przekazanie nazwy pliku do programu oznaczałoby, że plik wejściowy byłby widoczny. To może, ale nie musi mieć znaczenia dla programu, ale niektóre operacje można przyspieszyć, jeśli strumień jest widoczny.
  • Znajomość rzeczywistego pliku wejściowego pozwala Twojemu programowi na potencjalnie zapis do niego. Na przykład sed -ido edycji w miejscu. (Uwaga: ponieważ musi to utworzyć nowy plik za kulisami, nie jest to wzrost wydajności w porównaniu z innymi przekierowaniami, ale jest to krok wygody.)
  • Korzystanie z przekierowań powłoki umożliwia łączenie wielu plików, a nawet przekierowywanie procesów. sed [exp] < file1 file2a nawet sed [exp] < <(grep command). Szczegóły tego przypadku użycia można znaleźć w tym pytaniu: Podstawienie procesu i potok
Caleb
źródło
Zastępowanie procesów powinno działać bez konieczności określania wyniku; sed [exp] < <(grep command)będzie działał dobrze, ponieważ sed [exp] <(grep command)(ponieważ <(grep command)tworzy nazwany plik tymczasowy na długość polecenia, który sedjest w stanie samodzielnie otworzyć się bez pomocy powłoki).
ShadowRanger
2
  1. Biorąc pod uwagę, że command filepo prostu otwiera plik i od tego momentu działa tak, jakby był stdin, nie ma różnicy. Dzięki przekierowaniu powłoki po prostu wcześniej otwierasz plik (shell robi,) w przeciwieństwie do samego polecenia binarnego.

  2. Jeśli mówimy o cat file | command kontra command <file, to ten drugi jest preferowany. Nie zauważysz znaczącej różnicy wydajności między tymi dwoma, ale ta pierwsza jest niepotrzebnie skomplikowana (dodatkowy proces i bufor pamięci współdzielonej dla potoku, z ograniczoną przepustowością.) Ponadto nie możesz seek(arbitralnie zmienić pozycji wskaźnika pliku) w potoku, podczas gdy możesz w zwykłym pliku. Niektóre polecenia mogą wykorzystywać bardziej wydajny algorytm, gdy seekmożliwe jest -ing w pliku wejściowym.

alex
źródło
Powiedziałbym, że plik poleceń jest lepszy niż plik polecenia <, ponieważ polecenie może wykonać jakiś niesekwencyjny dostęp.
user606723,
A co powstrzymałoby to przed zrobieniem tego <file? Twoje uzasadnienie dotyczy używania nazwy pliku wejściowego do wyprowadzania trudnej nazwy pliku wyjściowego, np .: gzip fileprodukuje file.gz.
alex
może nie rozumiem, jak przekierowanie działa wewnętrznie. Powiedzmy, że przekierowujemy film 12 GB do mplayer / vlc, a następnie przechodzimy do końca. Co dokładnie by się stało w tym przypadku?
user606723,
1
Shell otwiera plik i wyświetla podproces, który dziedziczy deskryptor pliku. Rozwidloną proces closeów stdini połączeń dupna otwartym deskryptorze pliku, więc zastąpić stary stdin(który był jakiś tty w większości przypadków). Z punktu odtwarzacz filmów widzenia nie ma różnicy między tym i otwierania pliku przez jego nazwę w sam gracz. Deskryptor pliku jest widoczny w obu scenariuszach, więc kiedy przejdziemy do końca, nie będzie żadnej zauważalnej przez użytkownika różnicy.
alex