Кілька способів прискорити bash-скрипти

  1. Швидкість виконання скриптів
  2. Використання зовнішніх команд
  3. Використання регулярних виразів
  4. Висновок в консоль даних
  5. Використання зайвих команд

Думаю, не зроблю відкриття, якщо скажу, що в принципі bash-скрипти штука досить повільна Думаю, не зроблю відкриття, якщо скажу, що в принципі bash-скрипти штука досить повільна. Але це звичайно не критично, тому що все-таки головне завдання bash-скриптів - це автоматизація тих дій, які виконуються руками. Так що в порівнянні з ручним виконанням швидкість просто фантастична. Проте, буває необхідно прискорити скрипти, якщо обробляються якісь великі обсяги даних.

Швидкість виконання скриптів

Є певні чинники, які впливають на швидкість виконання скриптів. До них можна віднести:

  • Використання зовнішніх команд
  • Використання надмірно складних або просто неоптимальні регулярних виразів
  • Висновок в консоль якихось даних
  • Використання зайвих команд
  • Використання круглих або фігурних дужок (про це я писав окремо )
  • і т.д. (Можна доповнити в коментарях)

І, відповідно, хороший скрипт

  • Чи не використовує специфічні програми, які є не скрізь (вимагають установки додаткових пакетів)
  • Використовує мінімум зовнішніх команд
  • Використовує оптимізовані регулярні вирази (які, як не сумно, багато хто взагалі не використовують), наприклад, з мінімальним використання захоплюючих квантіфікаторов. Регулярки - це взагалі окрема цікава тема, з приводу якої можу порекомендувати книгу Джеффрі Фрідл «Регулярні вирази» (якщо ваш англійська дозволяє, то краще в оригіналі) і багато практики.
  • Чи не використовує змінні для зберігання даних, коли можна використовувати пайп і запускати два процеси паралельно замість послідовного запуску

Крім швидкості, природно, є ще такий фактор як сумісність. Якщо ви впевнені, що в інших оболонках скрипт виконуватися не буде, або буде працювати повільно, краще відмовтеся від сумісності на користь швидкості. Який сенс писати скрипти, які будуть в 99% випадків виконуватися в bash, але працювати будуть у 100% випадків повільно? Тим більше що bash є буквально всюди, навіть на смартфонах і роутерах. У наш час написання сумісних скриптів - це частіше питання переваг, ніж реальної необхідності. Не дуже приємно буває усвідомлювати, що скрипт може працювати під різними оболонками, але працює 100% в БАШЕЄВ, і, в зв'язку з відсутністю «заточування» під баш, працює він помітно повільніше, ніж міг би.

Тому давайте розглянемо деякі моменти, що стосуються швидкості скриптів на прикладах.

Використання зовнішніх команд

Виклик зовнішніх програм працює повільніше, ніж внутрішніх, відповідно, множинні виклики, наприклад, в циклі, будуть працювати повільніше, ніж внутрішні. приклад:

VAR1 = 123 VAR1 = $ (echo $ VAR1 | sed 's / 2. * / 45 /')

Мінлива VAR1 прийме значення «145». Але те ж саме можна зробити взагалі без використання sed'а. Ось так:

VAR1 = 123 VAR1 = $ {VAR1 / 2 * / 45}

Такий варіант краще не тільки тим, що не використовує sed, але і тим, що не використовує echo, і не використовується виклик окремого примірника інтерпретатора, з якого викликаються echo і sed. Давайте подивимося, як за часом відрізняються тисячі виконань перших двох команд і других двох команд. перші:

real 0m1.136s user 0m0.052s sys 0m0.064s

другі:

real 0m0.004s user 0m0.000s sys 0m0.000s

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

Використання регулярних виразів

Як я вже писав вище, тема дуже цікава і досить специфічна, але тут, я думаю, варто навести приклад. Чи не виключно пов'язаний з самою оболонкою bash, але пов'язаний з написанням сценаріїв. Простий приклад. У нас є певний файл, який містить рядки, з яких нам треба отримати певну інформацію. Рядки виглядають наступним чином: деякий числове значення, потім пробіл і якась рядок. Треба замінити пробіл на знак підкреслення.

Перший варіант:

#! / Bin / bash sed -r 's / ([0-9]) ([az]) / \ 1_ \ 2 /' file.dat

І другий варіант:

#! / Bin / bash sed 's / / _ /' file.dat

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

real 0m0.071s user 0m0.068s sys 0m0.000s

Другий скрипт:

real 0m0.019s user 0m0.016s sys 0m0.000s

Що, загалом, логічно. Непотрібні обчислення непотрібних даних. Я вже не кажу про регулярний вираз «(. *)», При використанні якого в скриптах, де обробляється багато даних, треба обов'язково подумати, чи треба використовувати зірочку. Загалом, у Фрідл з цього приводу добре написано.

Висновок в консоль даних

Я, природно, маю на увазі ті дані, які для роботи скрипта ніякої ролі не грають. Сам висновок на екран великої кількості даних може також гальмувати роботу скрипта і, просто відключивши непотрібний висновок, можна прискорити bash-скрипт. Перший скрипт:

#! / Bin / bash sed -r 's /(.*) (. *) / \ 1_ \ 2 /' file.dat

Другий скрипт:

#! / Bin / bash sed -r 's /(.*) (. *) / \ 1_ \ 2 /' file.dat> / dev / null

Як бачите, різниця тільки в тому, що перший скрипт виводить рядки в консоль, а другий в / dev / null. За часом вони відрізняються, природно, ось перший скрипт:

real 0m0.155s user 0m0.064s sys 0m0.040s

А ось другий:

real 0m0.078s user 0m0.064s sys 0m0.012s

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

Використання зайвих команд

Це досить поширений варіант, який часто пов'язаний з тим, що спочатку пишуть деякий скрипт, а потім або в поспіху, або через неуважність забувають прибрати зайве. Найчастіший варіант - використовували команду cat для виведення якогось файлу при дебаге парсинга в консолі, і вставили в тому ж вигляді в скрипт, хоча можна безпосередньо grep'у вказати брати дані з файлу. Або ще один приклад: використання зайвих команд echo. Команда внутрішня, звичайно, але якщо вона часто використовується, можна її все-таки рідше використовувати, якщо необхідна максимальна швидкість.

Перший скрипт:

#! / Bin / bash for i in {1..10000} do echo "1" echo "2" echo "3" done

Другий скрипт:

#! / Bin / bash for i in {1..10000} do echo -e "1 \ n2 \ n3" done

І, відповідно, час роботи цих двох сценаріїв. перший:

real 0m0.375s user 0m0.192s sys 0m0.092s

другий:

real 0m0.225s user 0m0.080s sys 0m0.068s

Що, загалом, логічно.

Ну, а про круглі і фігурні дужки я писав окрему статтю, яку ви можете подивитися тут .

І, як завжди, чекаю питання, доповнення, коментарі. Напевно у вас є свої приклади оптимізації bash-скриптів.

Який сенс писати скрипти, які будуть в 99% випадків виконуватися в bash, але працювати будуть у 100% випадків повільно?

Дополнительная информация

rss
Карта