Чому echo> файл використовує більше реального часу, ніж echo | sed> файл?


28

Приклад нижче, мене здивував. Це здається протилежним інтуїтивно зрозумілим ... окрім того, що у комбі є більше часу для echo | sedкомбо.

Чому echoвикористовується стільки системного часу, коли він працює самостійно, або має бути питання, як sedзмінюється стан гри? Здається, що в обох випадках echoпотрібно зробити те саме, що лунає ...

time echo -n a\ {1..1000000}\ c$'\n' >file

# real    0m9.481s
# user    0m5.304s
# sys     0m4.172s

time echo -n a\ {1..1000000}\ c$'\n' |sed s/^\ // >file

# real    0m5.955s
# user    0m5.488s
# sys     0m1.580s

1
Моя кишкова реакція пов'язана з буферизацією.
bahamat

1
@bahamat Я думаю, ти маєш рацію. Відлуння робить окремий запис () для кожного аргументу. Сід буферизує їх. Отже, перша версія має мільйон записів у звичайний файл, переходячи через драйвер файлової системи в рівень блокового пристрою, а друга версія має мільйон записів, що надходять у трубу, і дещо менша кількість записів проходить через більш дорогі шари коду ядра.
Алан Карі

@bahamat Безумовно буферизація. time echo ... |cat >fileі навіть time echo ... |perl -ne 'print'подібні часи до sedверсії.
StarNamer

4
Дякую всім за хороші пояснення ... Отже, для великих багаторядкових записів (у башті) кішка отримала корисне використання точки Cat :)
Peter.O

Відповіді:


29

Багам і Алан Каррі мають право: це пов'язано з тим, як ваша оболонка буферизує вихід echo. Зокрема, ваша оболонка є bash, і вона видає один writeсистемний виклик на лінію. Отже, перший фрагмент робить 1000000 записів у файл диска, тоді як другий фрагмент робить 1000000 записів у трубу, а sed (значною мірою паралельно, якщо у вас є кілька процесорів) робить значно меншу кількість записів у файл диска через його вихід буферизація.

Ви можете спостерігати за тим, що відбувається, бігаючи з напругою .

$ strace -f -e write bash -c 'echo -n a\ {1..2}\ c$'\'\\n\'' >file'
write(1, "a 1 c\n", 6)                  = 6
write(1, " a 2 c\n", 7)                 = 7
$ strace -f -e write bash -c 'echo -n a\ {1..2}\ c$'\'\\n\'' | sed "s/^ //" >file'
Process 28052 attached
Process 28053 attached
Process 28051 suspended
[pid 28052] write(1, "a 1 c\n", 6)      = 6
[pid 28052] write(1, " a 2 c\n", 7)     = 7
Process 28051 resumed
Process 28052 detached
Process 28051 suspended
[pid 28053] write(1, "a 1 c\na 2 c\n", 12) = 12
Process 28051 resumed
Process 28053 detached
--- SIGCHLD (Child exited) @ 0 (0) ---

Інші оболонки, такі як ksh буфер виведення, echoнавіть якщо це багаторядковий, тому ви не побачите великої різниці.

$ strace -f -e write ksh -c 'echo -n a\ {1..2}\ c$'\'\\n\'' >file'
write(1, "a 1 c\n a 2 c\n", 13)         = 13
$ strace -f -e write ksh -c 'echo -n a\ {1..2}\ c$'\'\\n\'' | sed "s/^ //" >file'
Process 28058 attached
[pid 28058] write(1, "a 1 c\n a 2 c\n", 13) = 13
Process 28058 detached
--- SIGCHLD (Child exited) @ 0 (0) ---
write(1, "a 1 c\na 2 c\n", 12)          = 12

З bash я отримую аналогічні співвідношення часу. З ksh я бачу, що другий фрагмент працює повільніше.

ksh$ time echo -n a\ {1..1000000}\ c$'\n' >file

real    0m1.44s
user    0m1.28s
sys     0m0.06s
ksh$ time echo -n a\ {1..1000000}\ c$'\n' | sed "s/^ //" >file

real    0m2.38s
user    0m1.52s
sys     0m0.14s

Дякую ... Цей останній kshприклад більше відповідає тому, що я очікував ...
Пітер.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.