Почему длительность выполнения команды при разных методах перенаправления разная?

Почему длительность выполнения команды при разных методах перенаправления разная?

Я запускаю findкоманду с заданным временем выполнения как обычный пользователь.

Я знаю, что перенаправление предназначено для предотвращения сообщений stdout/stderr на терминале. Если это так, то почему разные методы перенаправления занимают разное время? Связано ли это как-то со скоростью записи на tty или есть какая-то другая причина? Может ли кто-нибудь указать мне правильное направление для понимания этого?

$ id
uid=1000(user1) gid=1000(user1) groups=1000(user1),1001(user2)

$time find /
<truncated output>
real    0m13.902s
user    0m0.197s
sys 0m0.448s

$ time find /  >/dev/null  
<truncated output>
real    0m0.298s
user    0m0.068s
sys 0m0.206s

$time find /  2> /dev/null 
<truncated output>
real    0m13.279s
user    0m0.181s
sys 0m0.405s

$ time find /  > /dev/null 2>&1
real    0m0.306s
user    0m0.109s
sys 0m0.174s

решение1

Когда вашему процессу ( find) необходимо фактически записать вывод, это, очевидно, займет гораздо больше времени, чем когда вы указываете ему отбросить этот вывод.

  • При использовании find /, на ваш терминал отправляются как stdout, так и stderr, и он должен вывести оба (т. е. фактические результаты и все ошибки прав доступа и т. д.)

  • При использовании time find / >/dev/nullвы отбрасываете стандартный вывод команды, но все равно печатаете все ошибки (если они есть). Судя по вашим результатам, у вас много законных результатов и очень мало ошибок.

  • Когда вы используете time find / 2> /dev/null, стандартный вывод команды все еще отправляется на ваш терминал, но теперь вы просто отбрасываете stderr. Если бы вы искали через файловую систему, на чтение которой у вас нет разрешения, это было бы на самом деле довольно быстро.

  • Когда вы используете time find / > /dev/null 2>&1, вы отбрасываете стандартный вывод, а затем отправляете стандартную ошибку туда, куда отправляется стандартный вывод,... т. е. вы отбрасываете и то, и другое. Это ничего не выведет, и поэтому будет самой быстрой из всех команд.

решение2

Насколько я знаю, перенаправление предназначено для предотвращения сообщений stdout/stderr на терминале.

Ну, нет: вы также можете сделать перенаправление на файл:

find / > ~/all-the-files

Связано ли это как-то со скоростью записи на tty?

Одним словом, да.

Независимо от того, какой терминал вы используете (виртуальная консоль в Linux, локальный xterm, что-то через SSH-соединение), реальный эмулятор терминала должен отрисовывать все, что печатается на терминале, даже если в этом случае он скоро прокрутится. (Исключением moshздесь может быть соединение через).

При сетевом подключении также следует учитывать задержку передачи, некоторые данные могут быть буферизованы, если их много, то не все. Если вы перенаправляете что-то в /dev/null, оно нигде не сохраняется и не отрисовывается. Перенаправление в файл также будет быстрым при умеренных объемах данных, поскольку ОС, вероятно, кэширует записи в памяти и фактически записывает на диск только после этого лениво. При большом объеме данных запись на диск также может стать узким местом. (или, если вам удалось заставить процесс записывать вывод в режиме синхронного ввода-вывода)

Для программ, которые выдают много выходных данных, только процесс форматирования выходных данных ( printf()внутри процесса) и вызов ОС для их записи займут время, даже если данные будут перенаправлены в /dev/null. В таком случае это может быть даже быстрее, если вы сможете убедить программу полностью запретить вывод. Это, вероятно, не относится к find, я бы предположил, что это будет связано со скоростью ввода-вывода или накладными расходами системного вызова.

Также обратите внимание, что если вы findмногократно запускаете одно и то же дерево каталогов, то первый раз, скорее всего, будет медленнее, чем другие, поскольку в первый раз может потребоваться чтение с диска, а после этого большая часть данных будет кэшироваться ОС.

Связанный контент