Коли оптимізація не передчасна і, отже, не зла?


75

"Передчасна оптимізація - корінь усього зла" - це те, що майже всі ми чули / читали. Мені цікаво, яка оптимізація не передчасна, тобто на кожному етапі розробки програмного забезпечення (дизайн високого рівня, детальний дизайн, реалізація високого рівня, детальна реалізація тощо), яку міру оптимізації ми можемо враховувати, не переходячи її на темну сторону.



Відповіді:


116

Коли ви базуєте це на досвіді? Не зла. "Кожен раз, коли ми робимо X, ми зазнавали жорстокого хіта на продуктивність. Давайте цього разу плануємо оптимізувати або повністю уникати X".

Коли це відносно безболісно? Не зла. "Реалізуючи це як Foo, чи Bar, це займе стільки ж роботи, але теоретично, Bar повинен бути набагато ефективнішим. Давайте забороняємо це".

Коли ви уникаєте шалених алгоритмів, які страшенно масштабуватимуться? Не зла. "Наша технологічна ведуча каже, що запропонований нами алгоритм вибору шляху працює у фактичний час; я не впевнений, що це означає, але вона пропонує ми здійснити seppuku навіть для того, щоб його розглянути. Давайте розглянемо щось інше".

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


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


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

26
Я згоден зі Стівом тут, іноді "оптимізація" просто не варта, тим більше, що компілятори настільки прокляті. Приклад? якщо він iне підписаний, i / 2його можна замінити на i >> 1. Це швидше. Але він також більш виразний (не всі побачать ефект, навіть ті, хто все-таки може втратити час). Але найгірше те, що компілятор все-таки зробить це, так навіщо заплутати вихідний код;)?
Матьє М.

19
@Larry: Я цього не зробив, тому, мабуть, це хороший приклад.
Joris Meys

18
На мою думку, оптимізацію, навіть просту оптимізацію, слід також вважати злом, якщо вони впливають на редабілітацію / підтримку коду і не базуються на фактичних вимірюваннях продуктивності.
Барт ван Інген Шенау

14
@Matthew: Навчити їх чому? Брудні та непотрібні хитрощі? Чому? Якщо профілювання показує, що a i/2дійсно є гарячою точкою, і це (неймовірно, але припустимо) i>>1робить його швидшим, то зробіть це, і додайте коментар до нього, що це профілювання показало, що це швидше. Якщо це дійсно потрібно де завгодно (в чому я сумніваюся, оскільки, як сказав Матьє, компілятори повинні бути досить розумні, щоб зробити це самостійно), новачки дізнаються щось, якщо це не так (що, швидше за все), чому ви хочете підключити їх голови з непотрібним фольклором?
sbi

38

Код програми повинен бути максимально гарним, але код бібліотеки повинен бути максимально хорошим, оскільки ви ніколи не знаєте, як буде використовуватися ваша бібліотека. Отже, коли ви пишете код бібліотеки, він повинен бути хорошим у всіх аспектах, будь то ефективність, надійність чи будь-яка інша категорія.

Крім того, вам потрібно думати про ефективність при розробці програми та при виборі алгоритмів . Якщо він не розроблений для того, щоб бути ефективним, жоден ступінь хакерства не може зробити його більш ефективним після цього, і жодна мікрооптимізація не перевершить переважний алгоритм.


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

1
Вибачте, але "будь добре у всіх аспектах" звучить підозріло, як перенапруження. Плюс, це, мабуть, не реально - життя завжди йде про компроміси.
sleske

1
+1 для підкреслення фази проектування; якщо ви навмисно зважуєте її переваги, це не передчасно.
Натан Туггі

І навпаки, якщо ви ніколи не знаєте, як буде використовуватися ваша бібліотека, ви не знаєте, чи витрачає час на її вдосконалення взагалі якусь ділову цінність. Тож навряд чи це аргумент.
RemcoGerlich


17

Коли оптимізація не передчасна і, отже, не зла?

Важко сказати, що таке добро і зло. Хто має таке право? Якщо ми дивимось на природу, то, здається, ми запрограмовані на виживання з широким визначенням "виживання", яке включає передачу наших генів потомству.

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

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


3
Це освіжаюче бачити, як хтось привіз на цей старий каштан. Все, що потрібно, - це прочитати всю цитату Кнута, а не лише одне речення, так?
Роберт Харві

1
@RobertHarvey У мене там трошки домашня тварина - оскільки так багато, здається, цитують саме це одне речення, і стільки важливої ​​контекстної інформації в кінцевому підсумку втрачається в процесі. Я не впевнений, що це така чудова відповідь, оскільки я отримав репутацію. :-D

14

Повна цитата визначає , коли оптимізація не передчасно:

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

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


6
Так ... Це добре і добре збривати 90% часу, коли триває випадковий виклик функції, але, можливо, ви отримаєте більший вплив, подивившись на код, де ваша програма насправді витрачає 80% свого часу і гоління кілька відсотків там.

11

Ви завжди повинні вибирати "досить хороше" рішення у всіх випадках, виходячи зі свого досвіду.

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

Це означає, що вам не слід вибирати суперскладний файл "сортування 100 Gb шляхом прозорої заміни на диск", звичайний режим сортування, коли це буде простий сортування, але ви також повинні зробити хороший вибір для простого сортування в першу чергу. Сліпо вибираючи сортування бульбашок або "виберіть усі записи випадковим чином і подивіться, чи вони в порядку. Повторіть". рідко буває добре.


3

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


3

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

Також важливо знати, де саме є вузьке місце продуктивності - оптимізація частини коду, яка займає лише 5% від загального часу, щоб виконати звичайне користь.

Кроки 2 та 3 описують недочасну оптимізацію:

  1. Змусити це працювати
  2. Тест. Не досить швидко? Профілюйте це .
  3. Використовуючи дані з кроку 2, оптимізуйте найповільніші розділи коду.

Ви забули крок 0, який полягає в тому, щоб: правильно сконструювати додаток, щоб ви могли очікувати розумної продуктивності з самого початку.
Роберт Харві

Я говорив лише про детальний етап впровадження.
Горгі Косев

1
Я сумніваюся в кроці №3 - найчастіше найкращою відповіддю є з'ясування іншого підходу, щоб ви в першу чергу не робили повільний біт коду.
Лорен Печтел

1
Виберіть правильні структури даних.
жасонька

3

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

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


3

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

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

Хтось сказав: Спочатку зробіть це правильно, потім зробіть це швидко. Вони мали рацію.

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

Тож ці дурні дебати тривають і продовжуються :)

** Інша річ, за якою вони говорять, - вам більше не доведеться турбуватися про це, адже компілятори настільки хороші, а машини зараз такі швидкі. (KIWI - Kill It With Iron.) Не існує експоненціальних апаратних чи системних прискорень (зроблених дуже розумними працьовитими інженерами), які могли б компенсувати експоненціальні уповільнення програмного забезпечення (це робиться програмістами, які думають таким чином).


2

Коли вимоги або ринок спеціально вимагає цього.

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

Іншим прикладом можуть бути деякі типи вбудованих пристроїв. Візьмемо для прикладу гальмо ABS; по-перше, є безпека, коли ви потрапили на перерву, машина повинна загальмувати. Але є також продуктивність, ви б не хотіли затримок, коли потрапили на перерву.


0

Більшість людей називають оптимізацію передчасною, якщо ви оптимізуєте щось, що не призводить до "м'якого виходу з ладу" (він працює, але він все-таки марний) завдяки продуктивності.

Приклади реального світу

  • Якщо мій міхур займає 20 мс для запуску, оптимізація його до 1 мс швидкості не сприятиме покращенню загальної корисності, незважаючи на збільшення продуктивності на 2000%.

  • Якщо веб-сторінка завантажується 20 секунд, а ми зменшуємо її до 1, це може підвищити корисність веб-сайту з 0 до майже нескінченності. В основному те, що було зламано, тому що це було занадто повільно, зараз корисне.


Важливо зазначити, що якщо ваш сорт викликається 1000 разів протягом програми, оптимізація від 20 мс до 1 мс - це велика справа.
Beefster

0

Яка оптимізація не передчасна?

Оптимізація, яка виправляє відому проблему з ефективністю вашої програми або оптимізацію, яка дозволяє вашій програмі відповідати чітко визначеним критеріям прийняття.

Визначившись, потрібно встановити деякий час, щоб встановити виправлення, і слід оцінити користь від ефективності.

(тобто це не так - "Я думаю, що цей біт коду виглядає так, що він може бути повільним, я заміню X на використання Y, і це буде швидше").

Я стикався з безліччю передчасної "оптимізації", яка в кінцевому підсумку зробила код повільнішим - в цьому випадку я передчасно вважаю "не продуманий". Ефективність має бути орієнтована до оптимізації та після неї та лише код, який фактично покращує збережену продуктивність.


0

"Передчасна оптимізація - корінь усього зла" - це те, що майже всі ми чули / читали

Правда. На жаль, це також одна з найбільш (зловмисно) зловживаних цитат програмування усіх часів. Оскільки Дональд Кнут створив мем, варто додати оригінальний контекст із цитати:

Слід забути про невелику ефективність, скажімо, про 97% часу: передчасна оптимізація - корінь усього зла. Але ми не повинні пропускати наші можливості на критичних 3%. ... Хороший програміст ... розумно буде уважно переглянути критичний код; але лише після виявлення цього коду ... універсальним досвідом програмістів, які користуються інструментами вимірювання, було те, що їх інтуїтивні здогадки не вдається

Зауважимо, що Кнут говорив спеціально про швидкість виконання під час виконання .

.. Програмісти витрачають величезну кількість часу на роздуми або занепокоєння швидкості некритичних частин своїх програм.

Крім того, він написав цю статтю в 1974 р., Коли будь-які машинні ресурси, де преміальна та негативна кореляція між швидкістю виконання та ремонтопридатністю програми (більша швидкість - менш рентабельна), ймовірно, були сильнішими, ніж зараз.

Добре, щоб відповісти на ваше запитання, на думку Дональда Кнута, оптимізація НЕ є передчасною, якщо вона фіксує серйозне вузьке місце, яке було визначено (ідеально виміряне та визначене під час профілювання).

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

  • вузькі місця, які видно неозброєним оком і яких можна уникнути перед введенням, наприклад, кількість O (N ^ 2) зворотних переходів до бази даних з великим N, де існує альтернатива O (1)

Далі навіть не пов'язані зі швидкістю виконання програми:

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