Это на самом деле интересный вопрос. Поскольку использование дополнительных конвейеров требует больше времени на обработку ЦП, но также работает быстрее для больших входов на многоядерных ЦП из-за распараллеливания.
Случай № 1: большие входы
Я использовал следующую команду для построения ввода и времени ваших команд:
time echo N | awk '{ for(i=0;i<$0;i++) print i"@@\n "i"\n"i"\\" }' | COMMAND > /dev/null
где N - целое число, указывающее AWK, как долго должен быть тестовый ввод, а COMMAND - команда (или конвейер), которую вы хотите рассчитать.
Я запускаю тесты для N = 10 000 000 на 2-ядерном компьютере:
Версия Single Sed:
time echo 10000000 | awk '{ for(i=0;i<$0;i++) print i"@@\n "i"\n"i"\\" }' | sed 's/.*@@//;s/[[:space:]].*//;s/\(.*\\\).*/\1LATEST/' > /dev/null
Результат:
real 1m26.714s
user 1m35.196s
sys 0m1.212s
Конвейерная версия sed:
time echo 10000000 | awk '{ for(i=0;i<$0;i++) print i"@@\n "i"\n"i"\\" }' | sed 's/.*@@//' | sed 's/[[:space:]].*//' | sed 's/\(.*\\\).*/\1LATEST/' > /dev/null
Результат:
real 0m56.280s
user 1m46.404s
sys 0m0.972s
Как вы можете видеть, даже если дополнительные конвейеры добавляют около 11 секунд дополнительного времени обработки (пользователь + sys), на самом деле команде требуется примерно на 30 секунд меньше реального времени для завершения, поскольку вывод каждой из трех команд sed выполняется обрабатывается следующим, пока он еще работает. На моей машине это приводит к тому, что реальное время обработки составляет почти половину процессорного времени, что указывает на эффективное использование обоих процессорных ядер.
Однако для одноядерных машин дополнительная конвейерная обработка только добавит ненужные издержки, замедляя обработку.
Случай № 2: построчная обработка
С другой стороны, если вы пишете сценарий bash и используете свои команды sed для обработки отдельных строк, , что не следует делать , вывод, вероятно, слишком мал, чтобы наблюдать вышеупомянутый эффект распараллеливания. И версия Sed будет гораздо более эффективной.
Ниже приведены временные параметры только для 10 000 строк, обрабатываемых одна за другой:
time for ((i=1;i<=10000;i++)); do printf "$i@@\n $i\n$i\\ \n" | sed 's/.*@@//;s/[[:space:]].*//;s/\(.*\\\).*/\1LATEST/'; done > /dev/null
Результат:
real 0m27.430s
user 0m2.772s
sys 0m4.224s
Конвейерная седь:
time for ((i=1;i<=10000;i++)); do printf "$i@@\n $i\n$i\\ \n" | sed 's/.*@@//' | sed 's/[[:space:]].*//' | sed 's/\(.*\\\).*/\1LATEST/'; done > /dev/null
Результат:
real 0m57.274s
user 0m3.704s
sys 0m7.776s
Как видите, конвейерный sed работает более чем в два раза медленнее, чем одиночная команда sed.
Обратите внимание, что использование одного конвейера sed на большом входе (как в случае № 1) работает как минимум в 1000 раз быстрее, чем построчная обработка аналогичного ввода (как в случае № 2).