Використання ресурсів за допомогою string and here string


16

Ми можемо отримати той же результат, скориставшись наступними двома в bash,

echo 'foo' | cat

і

cat <<< 'foo'

Моє запитання - в чому різниця між цими двома, що стосується використаних ресурсів, а який - кращий?

Моя думка полягає в тому, що при використанні труби ми використовуємо додатковий процес echoі трубу, тоді як тут рядок використовується лише дескриптор файлу cat.

Відповіді:


17

Труба - це файл, відкритий у внутрішній файловій системі та недоступний як звичайний файл на диску. Він автоматично буферизується лише до певного розміру і з часом блокується після повного заповнення. На відміну від файлів, створених на блокових пристроях, труби ведуть себе як пристрої символів, тому, як правило, не підтримують, lseek()і дані, прочитані з них, не можуть бути прочитані знову, як це можна зробити зі звичайним файлом.

Тут-рядок - це звичайний файл, створений у змонтованій файловій системі. Оболонка створює файл і зберігає його дескриптор, негайно видаляючи єдине посилання файлової системи (і таким чином видаляючи його), перш ніж він запише / прочитає байт в / з файлу. Ядро буде підтримувати необхідний для файлу простір, поки всі процеси не випустять для нього всі дескриптори. Якщо дитина, що читає з такого дескриптора, має можливість це зробити, його можна перемотати lseek()і прочитати ще раз.

В обох випадках маркери <<<і |представляють дескриптори файлів, а не обов'язково самі файли. Ви можете краще зрозуміти, що відбувається, виконуючи такі речі:

readlink /dev/fd/1 | cat

... або ...

ls -l <<<'' /dev/fd/*

Найбільш суттєвою різницею між двома файлами є те, що тут-рядок / doc - це майже все одночасно - оболонка записує в неї всі дані, перш ніж запропонувати прочитаному дескриптору. З іншого боку, оболонка відкриває трубу на відповідних дескрипторах і відщеплює дітей для управління тими для труби - і так вона записується / читається одночасно на обох кінцях.

Ці відмінності, правда, лише загалом вірні. Наскільки я знаю (що насправді не все так далеко), це стосується майже кожної оболонки, яка обробляє <<<коротку руку тут-рядка для <<перенаправлення тут документа за єдиним винятком yash. yash, busybox,dash , І інші ashваріанти мають тенденцію до спини тут-документи з трубами, хоча, і тому в цих снарядів там дійсно дуже мало різниці між ними після всього.

Гаразд - два винятки. Тепер, коли я замислююся над цим, ksh93насправді взагалі не робиш трубку |, а, швидше, обробляє весь бізнес w / sockets - хоча це і видалений tmp-файл для <<<*більшості інших. Більше того, він розміщує лише окремі ділянки трубопроводу в середовищі підклітини, яка є своєрідним евфемізмом POSIX, принаймні, він діє як підзаглушка , і навіть не робить вилки.

Справа в тому, що результати @ PSkocik (що дуже корисно) результати тут можуть сильно відрізнятися з багатьох причин, і більшість з них залежить від реалізації. Для налаштування документа тут, найбільшими факторами будуть ${TMPDIR}тип цільової файлової системи та поточна конфігурація / доступність кешу, а ще більше кількість даних, що підлягають запису. Для труби це буде розмір самої оболонки, оскільки копії робляться для необхідних вилок. Таким чином, bashце жахливо при налаштуванні конвеєра (включати заміни $(команд )) - тому що він великий і дуже повільний, але зksh93 ним навряд чи є різниця взагалі.

Ось ще один маленький фрагмент оболонки, який продемонструє, як оболонка розбивається на підкладки для конвеєра:

pipe_who(){ echo "$$"; sh -c 'echo "$PPID"'; }
pipe_who
pipe_who | { pipe_who | cat /dev/fd/3 -; } 3<&0

32059  #bash's pid
32059  #sh's ppid
32059  #1st subshell's $$
32111  #1st subshell sh's ppid
32059  #2cd subshell's $$
32114  #2cd subshell sh's ppid

Різниця між тим, що конвеєрної розшифровкою pipe_who()дзвінків і звітом одного запуску в поточній оболонці обумовлена (подоболочкі в )зазначеному поведінку витребування PID батьківської оболонки в , $$коли він розширений. Хоча bashпідрозділи обов язково є окремими процесами, $$спеціальний параметр оболонки не є надійним джерелом цієї інформації. Тим не менш, дочірня shоболонка передплавки не відхиляється, щоб точно повідомити про неї $PPID.


Дуже корисний. Файлова система в ядрі, чи є для неї назва? це означає, що він існує в просторі ядра?
utlamn

2
@utlamn - насправді так - просто труси . Це все в ядрі - але (окрім таких речей, як FUSE), так само все файли вводу / виводу .
mikeserv

10

Немає заміни для тестування:

pskocik@ProBook:~ 
$ time (for((i=0;i<1000;i++)); do cat<<< foo >/dev/null; done  )

real    0m2.080s
user    0m0.738s
sys 0m1.439s
pskocik@ProBook:~ 
$ time (for((i=0;i<1000;i++)); do echo foo |cat >/dev/null; done  )

real    0m4.432s
user    0m2.095s
sys 0m3.927s
$ time (for((i=0;i<1000;i++)); do cat <(echo foo) >/dev/null; done  )
real    0m3.380s
user    0m1.121s
sys 0m3.423s

А для більшої кількості даних:

TENMEG=$(ruby -e 'puts "A"*(10*1024*1024)')
pskocik@ProBook:~ 
$ time (for((i=0;i<100;i++)); do echo "$TENMEG" |cat >/dev/null; done  )

real    0m42.327s
user    0m38.591s
sys 0m4.226s
pskocik@ProBook:~ 
$ time (for((i=0;i<100;i++)); do cat<<< "$TENMEG" >/dev/null; done  )

real    1m26.946s
user    1m23.116s
sys 0m3.681s
pskocik@ProBook:~ 

$ time (for((i=0;i<100;i++)); do cat <(echo "$TENMEG") >/dev/null; done  )

real    0m43.910s
user    0m40.178s
sys 0m4.119s

Здавалося б, трубна версія має більшу вартість установки, але зрештою є більш ефективною.


@mikeserv Це було правильно. Я додав орієнтир з більшим обсягом даних.
PSkocik

2
echo foo >/dev/shm/1;cat /dev/shm/1 >/dev/nullздавалося, що швидко в обох випадках ...
user23013

@ user23013 Це має сенс. Я не розумію, чому echo "$longstring"або не <<<"$longstring"було б налаштовано на ефективність і з короткими рядками, ефективність все одно не має великого значення.
PSkocik

Цікаво, що в моєму випадку (на Ubuntu 14.04, Intel quad core i7) cat <(echo foo) >/dev/nullшвидше, ніж echo foo | cat >/dev/null.
pabouk

1
@Prem Так, це був би кращий підхід, але ще кращим було б взагалі не турбуватися про це і використовувати правильний інструмент для роботи. Немає підстав думати, що гередоки будуть налаштовані на виставу.
PSkocik
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.