Logo Zephyrnet

Czy Twój mentalny model rurociągów Bash jest błędny?

Data:

[Michael Lynch] napotkał dziwną sytuację. Dlaczego kompilował, a następnie uruchamiał swój program prawie 10 razy szybciej niż samo uruchomienie programu? [Michael] natknął się na ten problem podczas porównywania projektu programistycznego, ograniczył go do najważniejszych elementów związanych z powtarzalnością i analizą i odkrył, że uwypuklił on nieprawidłowy mentalny model działania potoków bash.

Oto sytuacja. Pierwszą rzeczą, jaką robi uproszczony program [Michaela], jest uruchomienie timera. Następnie po prostu czyta i zlicza niektóre bajty stdin, a następnie wypisuje, ile czasu minęło, zanim to nastąpiło. Uruchamianie programu testowego w następujący sposób zajmuje około 13 mikrosekund.

$ echo '00010203040506070809' | xxd -r -p | zig build run -Doptimize=ReleaseFast
bytes: 10
execution time: 13.549µs

Przy bezpośrednim uruchomieniu (już skompilowanego) programu czas wykonania wzrasta do 162 mikrosekund.

$ echo '00010203040506070809' | xxd -r -p | ./zig-out/bin/count-bytes
bytes: 10
execution time: 162.195µs

Ponownie, jedyna różnica pomiędzy zig build run i ./zig-out/bin/count-bytes polega na tym, że najpierw kompiluje kod, a następnie natychmiast go uruchamia. Drugi po prostu uruchamia skompilowany program.

Jak dodać dodatkowy krok kompilacji spadek czas realizacji? Okazuje się, że mentalny model działania potoków bashowych [Michaela] był nieprawidłowy i radzi sobie świetnie wyjaśniając, jak faktycznie działają i dlaczego spowodowało to dziwne zachowanie widział.

Krótko mówiąc, polecenia w potoku bash nie są uruchamiane sekwencyjnie. Wszystkie są uruchamiane w tym samym czasie i wykonywane równolegle. Oznaczało to, że po bezpośrednim uruchomieniu program [Michaela] liczący bajty uruchamiał się natychmiast. Następnie czekał, nic nie robiąc, przez około 150 mikrosekund, podczas gdy echo '00010203040506070809' | xxd -r -p część potoku zabrała się za dostarczanie danych do programu do odczytania. Stąd bierze się dodatkowy czas wykonania podczas uruchamiania już skompilowanej wersji.

Dlaczego więc kompilacja przebiega szybciej? Z tego samego podstawowego powodu: kiedy zig build run polecenie się uruchamia, najpierw zajmuje trochę czasu na kompilację programu. Następnie, kiedy skompilowany program zostanie faktycznie uruchomiony (i rozpocznie się jego licznik czasu wykonania), dane wejściowe z potoku bash będą już gotowe. Zatem świeżo skompilowany program wykonuje się w krótszym czasie, ponieważ nie czeka, aż staną się dostępne dane z wcześniejszej fazy potoku.

To interesujące spojrzenie na to, jak faktycznie działają potoki bashowe pod maską i jesteśmy zachwyceni szczegółami, jakie [Micheal] wkłada w całą podróż i wyjaśnienia. Wcześniej czy później takie szczegóły pojawiają się i powodują uniesienie brwi, podobnie jak użytkownik, który odkrył kłopotliwe przypadki Edge dotyczące spacji w poleceniach ssh.

spot_img

Najnowsza inteligencja

spot_img