Korzystanie z stdout jest wolne

UWAGA! Ten wpis ma już 9 lat. Pewne stwierdzenia i poglądy w nim zawarte mogą być nieaktualne.

Całe życie byłem przekonany, że wypluwanie danych do stdout jest najszybszym sposobem prezentowania postępu działania aplikacji działającej w CLI. I dopiero parę dni temu, przez przypadek, dowiedziałem się, że grubo się myliłem.

Weźmy na warsztat prosty skrypt:

$start = microtime(true);

for($i = 0; $i < 1000000; $i++) {
    echo 'New line' . PHP_EOL;
}

$stop = microtime(true);

$totalTime = $stop - $start;

echo 'Execution time: ' . $totalTime . PHP_EOL;

Wykonanie w moim przypadku zajmuje ~6,5 s.

Podobny skrypt uruchomiłem niedawno przez przypadek w pracy, jednak zapomniałem odkomentować wyświetlania linii tekstu. Skrypt wykonał się… praktycznie od razu.

Zakomentujmy więc linię zawierającą echo 'New line’ . PHP_EOL; . Po tym zabiegu wykonanie skryptu trwa ok. 0,16 s. Różnica jest więc ogromna.

Po chwilowym szukaniu informacji na ten temat, pomocny okazuje się jak zwykle wątek na stackoverflow. W skrócie: stdout nie jest przystosowany do przetwarzania dużej ilości informacji, natomiast „fenomen” zauważony przez pytającego (zapis na dysk jest szybszy od wyplucia danych do stdout) wynika z buforowania. Dodatkowo, są duże różnice pomiędzy poszczególnymi emulatorami terminala.

Na przyszłość będę więc oszczędniejszy w korzystaniu z stdout, zwłaszcza, gdy zależy na czasie.

2 komentarze do “Korzystanie z stdout jest wolne”

  1. Jeśli zależy na czasie, można przekierować STDOUT do /dev/null. Oczywiście jest to wolniejsze, niż brak wyświetlania, ale znacznie szybsze od wyświetlania na ekran:
    time perl -e 'for (1..100000){print „$_\n”}’
    real 0m1.280s
    time perl -e 'for (1..100000){print „$_\n”}’ > /dev/null
    real 0m0.056s

    Z innych tricków, które lubię – warunkowe wyświetlanie. Zmienna $debug lub $verbose, która określa, czy skrypt ma być gadatliwy, a potem:
    print „komunikat” if $debug;
    Dzięki temu przez zmianę jednej zmiennej można ograniczyć ilość danych pisanych na STDOUT.

  2. Huh, widzę, że cudzysłowy pojedyncze i podwójne są psute w komentarzach. Znaczy otwierające są zamieniane na dolne, co – jak widać – ssie.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Time limit is exhausted. Please reload CAPTCHA.