Чи дозволено оболонці оптимізувати непотрібні команди закінчення?


27

Якщо оболонці запропоновано виконати ймовірно марну ( або частково непотрібну ) команду, відому для завершення, наприклад cat hugeregularfile.txt > /dev/null, чи може вона пропустити виконання цієї команди ( або виконати більш дешевий еквівалент, скажімо, touch -a hugeregularfile.txt )?

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

EDIT

Нота Бене: У моєму запитанні, яке було задано спочатку, було вказано заголовок, який запитував, чи дозволяється оболонці робити ці оптимізації, а не чи слід, чи існують такі реалізації, які можуть їх виконати. Мене теорія цікавить більше, ніж практика, хоча обидва вітаються.


Ні, оболонка не така розумна, як сучасні компілятори. Насправді це досить тупо. Це не оптимізувало б жоден марний код.
devnull

12
Відгадування того, що призначений користувачем, - це не те, що повинна робити оболонка. Користувач може намагатися зробити майже що-небудь з цією командою, оптимізація її буде неправильною, навіть якщо це можливо.
Кріс Даун

1
Незалежно від того, що якщо файл був пристроєм, то catтинг - це має велике значення. Оболонка може дізнатися, що файл - це пристрій, але він не повинен бути надійним.
йо

3
@StephaneChazelas C компіляторам не потрібно "просити дозволу у кого-небудь" для оптимізації складених програм; У стандарті С є правило нібито, яке дозволяє їм це робити. Здається, що стандарт POSIX має стандартизовану щонайменше одну оболонку ( pubs.opengroup.org/onlinepubs/009695399/utilities/… ), а також численні інші утиліти ( pubs.opengroup.org/onlinepubs/009604499/utilities/wc.html для wc, наприклад). Але наскільки мені відомо, POSIX не займає позиції щодо оптимізації оболонок; Або це?
Iwillnotexist Idonotexist

2
Оптимізація - це підвищення продуктивності за допомогою ярликів, не впливаючи на функціональність. Поки функціональність гарантована, я не бачу заперечень POSIX. Ваша запропонована оптимізація хоч би порушила котячі характеристики . У специфіці POSIX є конкретні формулювання, які відповідають типу оптимізації, виконаної компанією ksh. Як і вони не говорять про окремий процес, а про підзарядне середовище, що дозволяє оптимізувати економію форк.
Стефан Шазелас

Відповіді:


26

Ні, це було б поганою ідеєю.

cat hugeregularfile.txt > /dev/nullі touch -a hugeregularfile.txtне однакові. catпрочитає весь файл, навіть якщо ви перенаправляєте вихід на /dev/null. І читати весь файл може бути саме тим, що ви хочете. Наприклад, щоб кешувати його так, щоб наступні читання були значно швидшими. Шкаралупа не може знати вашого наміру.

Так само компілятор C ніколи не оптимізує читання файлу, навіть якщо ви не дивитеся на прочитані вами речі.


2
@Iwillnotexist: Кожна корисна команда (крім, певно, trueі false) має потенційні побічні ефекти, і побічні ефекти майже завжди є точкою виклику команди. Оболонка не могла знати заздалегідь ці побічні ефекти (для зовнішніх програм, таких як cat), не вирішивши проблему зупинки. Тож правильно не намагається, і припускає, що ти мав на увазі те, що ти сказав.
cHao

5
@IwillnotexistIdonotexist Ні, оболонка не може побачити все, що має відбутися. Про це не має уявлення cat. Насправді, catможна було б зробити що завгодно - від форматування вашого жорсткого диска до завантаження в Інтернет.
scai

5
"Unix не був створений для того, щоб перешкоджати користувачам робити дурні речі, оскільки це також заважало їм робити розумні речі". - Doug Gwyn
Agi Hammerthief

7
@cHao І навіть trueі falseвстановити $?.
Кайл Странд

3
Як зазначав @scai вище, виконувані файли не схожі на мовні ключові слова: catі /dev/nullмають типові значення, але вони не гарантують себе таким чином. Для здійснення оптимізацій, гарантуючи відсутність змін у очікуваній поведінці, оптимізація може бути дозволена лише за участю конструкцій, реалізованих у самій оболонці, а не речей, знайдених у середовищі виконання ... незалежно від того, наскільки інтуїтивно можуть виглядати їх назви.
andybuckley

20

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

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

Ваше порівняння з оптимізацією відібраного коду в програмі C не працює, оскільки оболонка не має загального огляду, який має компілятор C над частиною вихідного коду. Оболонка не знає достатньо, /dev/nullщоб оптимізувати ваш приклад за межами, більше, як компілятор C недостатньо знає код у функції, виклик якої динамічно посилається, щоб не здійснювати виклик.


4
Як виявляється, ksh93 поводиться /dev/nullспеціально, іноді. Вбудований, який спрямовує свій stdout /dev/null, наприклад echo foo >/dev/null, не призведе до того, щоб робити якісь записи /dev/null. Він не робить нічого особливого, якщо викликає невбудовану команду (наприклад, cat file >/dev/null).
Марк Плотнік

Фактично, catтакож може бути щось інше. Що-небудь ще насправді.
Оріон

3
На насправді /dev/nullце одна з дуже небагатьох стандартних шляхів , а також /dev/tty, /dev/console, /tmp, /dev/і /.
Жил 'ТАК - перестань бути злим'

2
@MarkPlotnick На насправді cat це ksh93 вбудований (не включений , якщо не ставити /opt/ast/binперед тим /bin(або де - небудь catє) в $PATH). І так, хоча cat file > /dev/nullз цим вбудованим readконтентом робиться вміст file, він не записує його в / dev / null (хоча він відкриває і закриває його).
Стефан Шазелас

14

Він не оптимізує запущені команди (і ви вже отримали ряд тонких відповідей, в яких повідомляється, чому цього не слід), але він може оптимізувати вилки, труби / socketpairs, читається в деяких випадках. Оптимізація, яку вона може робити:

  • У більшості сучасних оболонок остання команда в скрипті, як правило, виконується в процесі оболонки, якщо не встановлені деякі traps. Наприклад , в sh -c ls, більшість shреалізацій ( bash, mksh, ksh, zsh, yash, деякі версії ash) НЕ розщедритися процесом для запуску ls.
  • в ksh93, підміна команд не створить "pipe" або "fork" процес, поки не буде викликана зовнішня команда ( $(echo foo)наприклад, розшириться на fooбез pipe / socketpair або fork).
  • readвбудована в деяких оболонках ( bash, AT & T ksh) не робитиме однобайтном читає , якщо вони виявляють STDIN є доступним для пошуку (в цьому випадку вони будуть робити великі читання і шукати назад до кінця , що вони призначені для читання).

Мені подобається ця відповідь, але незрозуміло, чи це оригінальна причина, чи інформація взята з якоїсь посилання (про яку я хотів би поглибитись)
yoniLavi

3
@yoniYalovitsky, це оригінальна причина . ksh93це оболонка, яка веде шлях на фронт оптимізації, оскільки її мета / повинна була розглядатися як однакова з такими мовами програмування perl. Таким чином, ви можете ознайомитися з kshдокументацією, кодом (удачі) та списком розсилки для отримання додаткової інформації.
Стефан Шазелас

1
@HenkLangeveld, так, ви можете перевірити, що з чим sh -c 'ps -p "$$"'дасть вам, psа не shз тими shреалізаціями, або з strace / truss / tusc ...
Stéphane Chazelas

1
Різниця між ksh -c 'ps; ps'і bash -c 'ps; ps' цікава. Ksh93 йде далі у своїй оптимізації.
Хенк Лангевельд

1
@HenkLangeveld, залежить про те, про що kshми тут говоримо. mkshповодиться як bash. Така поведінка в основному призначена для оптимізації таких речей system("some command"). Зауважте, що є побічний ефект цієї оптимізації, коли мова йде про стан виходу процесів, закінчених сигналом (у деяких оболонках). ksh93раніше помилка в тому, що вона робила оптимізацію, навіть коли встановлювалися пастки.
Стефан Шазелас

7

Побачивши cat hugeregularfile.txt > /dev/null, оболонці не дозволяється повірити, що дія марно - catне є частиною оболонки і могла б зробити що-небудь взагалі теоретично, а також на практиці.

Наприклад, користувач може перейменував виконуваний rmдо cat, і раптом лінія виконує зовні спостерігається поведінка, тобто видалення файлу.

Користувач, можливо, склав версію, catяка переходить у нескінченний цикл, тому оболонка не може припустити, що вона «відома, що закінчується», як ви пропонуєте.

Хтось, можливо, встановив версію, catяка працює за призначенням, але з додатковим побічним ефектом встановлення руткіта, якщо він коли-небудь запускається з відповідними привілеями - знову ж, оболонка повинна належним чином виконати його.


2
Насправді, mkshнасправді оптимізується V=$(cat file), роблячи його вбудованим. Таким чином оболонка може оптимізувати її, але не перетворювати її на лише a touch -a.
Стів Шнепп

1
@SteveSchnepp, cat це є вбудованої в mksh, але що BUILTIN вдається до системи , catякщо він прийнятий який - або варіант, тому з GNU cat, mksh -c 'cat /dev/null --help'не дає такої ж результат , як bash -c 'cat /dev/null --help', але mksh -c 'cat --help /dev/null'це дасть вам те ж саме bash -c 'cat --help /dev/null'(як mkshкішки вбудовано розбирає опцій POSIX Таким чином, в той час як кішка GNU розбирає їх із способом GNU).
Стефан Шазелас

У bash та ksh93, V=$(cat file)оптимізацію можна використовувати за допомогою V=$(< file). Це пришвидшує речі навіть без вбудованого cat.
Хенк Лангевельд
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.