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


178

Нещодавно я задав питання щодо переповнення стека, щоб з’ясувати, чому isset () був швидшим, ніж strlen () в PHP . Це поставило питання про важливість читабельного коду та про те, чи варто навіть покращення продуктивності мікросекунд коду.

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

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

Фактори навколишнього середовища можуть бути важливими - Інтернет споживає 10% світової енергії. Цікаво, наскільки марнотратним є кілька мікросекунд коду, коли вони повторюються в трильйони разів на мільйонах веб-сайтів?

Я хотів би знати відповіді, бажано на основі фактів програмування.

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

Моє особисте резюме з 25 відповідей, дякую всім.

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

if (expensiveFunction() || counter < X)

Має бути

if (counter < X || expensiveFunction())

( Приклад від @ zidarsk8 ) Це може бути недорогою функцією, і тому зміна коду буде мікрооптимізацією. Але, з основним розумінням, вам би не довелося, тому що ви б написали це правильно в першу чергу.


123
Поради батька застарілі . Я б не питав, наскільки це покращує продуктивність. Я б запитав, де вузьке місце. Не має значення, якщо ви покращуєте продуктивність розділу коду, якщо він не має загальної різниці, ваше найповільніше посилання буде визначати швидкість. У PHP це написання в мережу (якщо ви не можете довести IE міру іншого); що перекладається на написання більш читабельного коду, важливіше.
Мартін Йорк

61
Якщо ключовим словом вважається, він не помиляється. Ви повинні мати якусь підказку про це.
JeffO

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

13
Чи можете ви надати джерело про "10% світової енергії"?
Михайло Пасха

17
coder does not consider performance in their code even at the micro level, they are not good programmersдуже відрізняється від мікрооптимізації. Це просто гарне кодування.
woliveirajr

Відповіді:


90

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

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

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

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

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

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


120

Мікрооптимізація важлива лише в тому випадку, якщо цифри говорять, що вона є.

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

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


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

7
@Mavrik Це правда. Якщо у вас є дві функції, X і Y, а Y швидше, ніж X (принаймні, для ваших конкретних умов), немає причин не використовувати Y, якщо код все ще є читабельним і доступним для обслуговування. Але якщо ви не знаєте про Y, і вам потрібно переробити код рефактора, щоб використовувати Y замість X, а продуктивність (цього сегмента коду) не є проблемою, то немає ніяких причин для цього зміни. Вся справа в компромісах - продуктивність, час, витрати, зусилля, читабельність / ремонтопридатність тощо.
Thomas Owens

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

+1 високооптимізований код є менш читабельним та ретельним ... але не завжди.
Боз

Більше випадків, коли продуктивність важлива: (1) ігрові; (2) великі обсяги даних; (3) веб-сайт з високим трафіком; (4) реагування на дуже складний інтерфейс користувача; (5) сервіс, який повинен працювати у фоновому режимі, як перевірка вірусів; (6) фінанси; (7) смартфон; і так далі. Це навряд чи обмежується езотеричними випадками, такими як RTS та вбудовані системи.
Рекс Керр

103

Всякий раз , коли хто - небудь запитає про оптимізації , я нагадав про цитаті з Майкла А. Джексона

Перше правило оптимізації програми: не робіть цього.

Друге правило оптимізації програми (лише для експертів!): Не робіть цього ще .

Цитата з Вікіпедії виправлена ​​на англійську англійську мову. * 8 ')

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

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

Навіть на C ви повинні бути досить хорошими в оптимізації, щоб знати більше про оптимізацію розділу коду, ніж компілятор.

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

isset()проти strlen()в PHP

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

Мало того, але немає жодної гарантії, яка isset()завжди буде більш ефективною, просто тому, що зараз вона ефективніша. Зараз оптимізація може бути не оптимізацією в наступному році, або через 10 років. Процесори, системи, компілятори з часом вдосконалюються та змінюються. Якщо продуктивність PHP strlen()є проблемою, PHP в майбутньому може бути змінено, то для оптимізації коду, можливо, потрібно буде видалити всі оптимізації isset ().

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

Приклад з особистого досвіду

Як приклад такої антиоптимізації , мені одного разу довелося переосмислити величезну кодову базу, наповнену кодом форми, if x==0 z=0 else z=x*yтому що хтось зробив припущення, що множення плаваючої точки завжди буде дорожче, ніж гілка. У оригінальній цільовій архітектурі ця оптимізація зробила код швидшим на порядок, але час змінюється.

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

Проблеми, які нам сьогодні доводиться оптимізувати, сильно відрізняються від тих, які ми мали оптимізувати 20 або навіть 10 років тому.

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


3
Ви хочете уникнути промивання трубопроводу та кешу - D Вони мають жахливі витрати. але лише на частини коду, які виправдовують їх багато-багато-багато-багато разів.
deadalnix

7
Я хотів би додати, що компілятори пройшли довгий шлях і оптимізують багато речей для вас. AFAIK, вони краще оптимізують чистий, читабельний код, ніж хитрі речі.
Becuzz

3
+1 за надання справжнього прикладу мікрооптимізації, що витрачає час - і виявляє, що Майкл Джексон був програмістом.
Боз

1
+1 Для прикладу. Це чудово ілюструє, чому слід залишити тривіальні перетворення компілятору.
back2dos

1
@Rex Kerr> у прикладі, вартість пов'язана з розгалуженням, що спричиняє змивання конвеєра процесора. Множення з плаваючою комою теж дороге. Що дорожче, сильно залежить від FPU та довжини конвеєра ЦП, на якому працює код. Я не був би здивований, що цей код працював швидше на старих процесорах, які мають коротший конвеєр і менш ефективний FPU, ніж поточний процесор.
deadalnix

84
  1. Напишіть код, який є чистим, стислим, простим і зрозумілим.
  2. Зробіть тести на ефективність, щоб виявити вузькі місця.
  3. Оптимізуйте критичні розділи.

Як правило: 95% вашого коду виконується 5% часу. Немає сенсу в оптимізації перед тим, як профайлювати / орієнтувати код і бачити, які 5%, які виконуються у 95% часу.

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

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

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


2
Найкраща відповідь для мене була помітна в Посібнику розробника Bugzilla: "Якщо ви намагаєтеся бути розумним, а не намагаєтесь читати, то, можливо, ви намагаєтесь зробити речі" швидшими? ". Якщо так, просто пам’ятайте : не вирішуйте проблему, перш ніж ви зрозумієте, що вона існує. Якщо ви не знаєте (фактичними детальними тестами), що ваш код повільний, не хвилюйтеся про те, щоб зробити його "швидшим". Це не лише обмежується оптимізація - багато програмістів постійно вирішують проблеми, яких ніхто ніколи не відчував. Не робіть цього ". bugzilla.org/docs/developer.html#general
Марко

7
Я взагалі згоден - окрім одного рядка, я стверджую, що "кожен ідіот вважає, що може мікрооптимізувати" ...;)
Нім

@Nim: Точка взята;)
back2dos

26

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

Я погоджуюсь з більшістю інших коментарів - те, що раніше робило програми C швидше, може не робити цього сьогодні, - але є й інші серйозні речі, які слід враховувати: чи варто використовувати C або C ++? Класи з простими перевантаженими операторами можуть вбити продуктивність, якщо ви їх багато використовуєте. Це має значення? Це залежить від вашої заявки, але якщо ви навіть не ВРАЖУЄте це, ви не дуже хороший програміст. Деякі люди можуть розглянути це протягом приблизно 2 мілісекунд і відхилити його, але я думаю, що занадто багато буквально навіть не вважають це.

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

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

Наприклад, скажіть, що ви написали щось на зразок Angry Birds на ПК або для ігрової консолі. Ви не звернули уваги на оптимізацію у вашій фізичній системі та графічній системі - адже подвійні ядра 2,5 ГГц в даний час є мінімальними, і ваша гра працює досить добре. Тоді приходять смарт-телефони, і ви хочете портувати його. Ах, чорт, ядро ARM 600 МГц ?

Подумайте про веб-сайт - щось спільне у вихідні, як « гаряче» чи «ні» . Ви використовуєте будь-яку зручну базу даних, пишете все, маючи на увазі швидкий розвиток, запускайте, надсилаючи по електронній пошті друзям URL. Через три місяці ваш сервер вмирає від перевантаження, і ви нічого не можете зробити, щоб збільшити масштаб. Це відбувається постійно. На найбільших веб-сайтах є рахунки за електроенергію, вимірювані сотнями кіловат або навіть мегават. Подумайте про це, є мегават, який потрібно зберегти за допомогою оптимізації коду.

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

Це не популярна думка на цих сайтах. До побачення репутація балів ....


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

3
Ваш приклад Angry Birds показує саме те, чому вам не слід оптимізувати передчасно. Переносячи з робочого столу на консоль мобільні пристрої, ви маєте справу з (принаймні) трьома дуже різними типами обладнання та оптимізація для одного може зашкодити замість допомоги іншому. Гірше, що оптимізація зробить код важчим для розуміння, а отже, важче портювати. Звичайно, виберіть ефективні алгоритми з самого початку, але збережіть мікрооптимізацію для фази настройки продуктивності, коли реальні дані підкажуть, де проблема на кожній платформі.
Калеб

@Caleb: Приклад Angry Birds ілюструє, чому б не оптимізувати для конкретного обладнання. Він також ілюструє, як ви можете створити цілу програму, не заважаючи робити більш загальні оптимізації на рівні C, а потім згоряти. Насправді не згоріли, але у вас проблеми, що виходять за рамки вашого первісного наміру.
phkahler

25

Давайте спочатку візьмемо ваш випадок: PHP

  • Я не думаю, що PHP - це не така мова (як за своєю природою, так і за основною областю застосування), що вам потрібно хвилюватися з приводу цих "мікрооптимізацій". PHP-код в основному оптимізований за допомогою кешування кодів.
  • Програми, написані на PHP, не пов'язані з процесором, вони в основному пов'язані з входом / виводом, тому ці оптимізації в будь-якому разі не варті вашого часу.
  • Все, що ОБОВ'ЯЗКОВО оптимізувати, ймовірно, повинно бути пришпилено до розширення C, а потім динамічно завантажене під час виконання PHP
  • Отже, як ви бачите, ми не отримуємо жодних стимулів шляхом мікрооптимізації нашого коду в PHP - з іншого боку, якщо ви витратите цей час на те, щоб зробити PHP-код більш читабельним та ремонтопридатним - це виплатить вам більше дивідендів.

Загалом,

Я б не витрачав "TOOOOO" багато часу на оптимізацію свого коду на такій динамічній мові, як Python або Ruby - адже вони НЕ розроблені для завдань, що вимагають великих процесів на читання процесора. Вони вирішують різні класи проблем, коли детально моделювати ситуацію в реальному світі (яку легко читати і підтримувати) - що називається експресивністю - важливіше швидкість. Якби швидкість була головним питанням, вони б не були динамічними в першу чергу.

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

Отже, щоб відповісти на ваше первісне запитання - "Чи важлива мікрооптимізація при кодуванні?" - відповідь - ЗАВИСИМО -

  • Що ви робите: домен програми, складність?
  • Чи дійсно покращення швидкості мікросекунди важливо для вашої програми?
  • Яка оптимізація буде найбільш вигідною? Це не завжди може бути оптимізація коду, але щось зовнішнє.
  • Скільки «користі» (з точки зору швидкості) ви пожинаєте за той час, коли вкладаєте мікрооптимізацію?
  • Чи можна досягти кращої швидкості іншими способами - шляхом зміни апаратного забезпечення, оперативної пам’яті та процесора, виконання коду паралельно або в розподіленій системі?

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


18

Здається, існує багато відповідей, які говорять про мікрооптимізацію

все про компроміси - ефективність, час, витрати, зусилля, читабельність / ремонтопридатність тощо.

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

if (counter < X && shouldDoThis()) // shouldDoThis() is an expensive function

завжди приємніше, ніж

if (shouldDoThis() && counter < X ) 

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

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


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

4
Це дуже небезпечний приклад. Оптимізація не повинна ніколи змінити поведінку . Навіть припускаючи, що cheap() && expensive()це оптимізація, expensive () && cheap()пропонує людям сліпо заміщати одне іншим, не враховуючи суттєвих смислових змін, які він створює (мовами, де &&є оператор короткого замикання).
Марк Бут

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

3
@MarkBooth Я маю згоду з phkahler тут, жодна з цих функцій не повинна мати побічних ефектів! Порядок кондиціону у заяві if не повинен впливати на результат програми. Мій приклад було б краще записати так if (x<100 && isPrime(x)), просто щоб зробити його більш зрозумілим.
zidarsk8

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

11

На початку моєї кар’єри, бланкетні твердження, такі як "не мікрооптимізуйся", призвели до великої сум'яття. Все є побічним; таким чином, люди кажуть, що "найкраща практика", а не "робити це".

"Краща практика" - найкращий вибір, враховуючи всі обставини. Наприклад, LINQ та Entity Framework повинні використовуватися замість вбудованого SQL. У моїй компанії ми на SQL Server 2000 . SQL Server 2000 не підтримує Entity Framework. Найкращі практики вимагають:

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

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

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

" Для всього, що є сезон, час для кожної діяльності під небом ".


1
До речі, ви можете використовувати Dapper як мікро-ORM альтернативу вбудованому SQL.
Дан

2
LINQ and Entity Framework should be used in lieu of inline SQL- Поки вам фактично не потрібен вбудований SQL, щоб щось оптимізувати; SQL, який виробляє EF, не завжди є оптимальним.
Роберт Харві

1
fwiw, якщо ваш начальник турбується про витрати на ліцензування SQL 2k8 (або будь-що інше, що може бути поточним), вам слід зазначити, що він досить старий, щоб незабаром з'являтися на EOL ДУЖЕ (якщо його ще немає)
warren

@warren - Деякі компанії не враховують таких речей. Для деяких, якщо це все ще "працює", вони не будуть модернізувати. Під роботою я маю на увазі, що сервер все ще працює. Ми вже бачимо відсутність підтримки з EF. Це просто недостатньо, щоб переконати їх витратити будь-які гроші.
P.Brian.Mackey

1
Просто ви знаєте, що ви можете використовувати EF з SQL 2000. Дизайнер не працює, але фактична структура сутності підтримує SQL 2000. Щоб обійти обмеження дизайнера, ви можете створити локальну базу даних в sql 2008 express з тією ж схемою. як база даних sql 2000, вкажіть на це дизайнера, щоб генерувати всі класи, потім перейдіть у файл .edmx та змініть цільову версію бази даних на 2000 та вкажіть рядок підключення до вашої бази даних sql 2000. Не найкраще рішення, але якщо ви не можете оновити, воно працює.
Ніл

8

Це завжди компроміс.

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

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

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

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

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

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

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

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


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

Технічне обслуговування та еволюція +1 є більш цінними, ніж мікрооптимізація. Хоча я впевнений, що комп’ютерна індустрія - це більше, ніж просто гроші? Наприклад, з відкритим кодом, освіта, інновації, управління, громада тощо. Я впевнений, що гроші можна знайти в корені цього, але це стосується більшості речей.
Боз

@Boz kay> Це частково так. По-перше, тому, що ваш начальник і підопічний здебільшого не знають нічого про дроти та піклуються про гроші. Якщо ви хочете просувати деякі інструменти з відкритим кодом, ви повинні сказати їм, як це покращить бренд компанії або як зменшить витрати на розвиток. Крім того, зробити розробників щасливим - це спосіб отримати хороший розробник у вашій компанії. Хороший розробник заробляє гроші (в основному кидає якість та інновації). Зрештою, гроші - це ключ. І я пишу, що з мого комп'ютера під Linux є великим прихильником безкоштовного програмного забезпечення. Те саме стосується освіти.
deadalnix

8

Вистава - це особливість

Стаття Джеффа Етвуда чудова для створення веб-сайту з високою ефективністю та важливості цього ...

Однак, не слід зосереджуватися на мікрооптимізації, поки не потрібно. Є більш економічно вигідна оптимізація, яку ви можете виконати. Зосередьтеся на архітектурі, а не на коді. Більшість веб-сайтів, які я бачив, повільно мали проблеми з високим рівнем (непотрібний рівень веб-сервісу, поганий дизайн бази даних, надмірно складна архітектура), які не тільки негативно вплинули на продуктивність, але були глибоко вкорінені і їх важко виправити.

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


7

Час розробника коштує більше, ніж час на комп’ютері. Це, як правило, те, що ви хочете оптимізувати. Але:

  • Існує різниця між мікрооптимізацією та алгоритмічною складністю. Витратьте достатньо часу, щоб бути впевненим, що ви використовуєте правильний алгоритм .
  • Переконайтеся, що ви ставите правильне запитання, select (select count(*) from foo) >= 1це не те саме, що select exists(select 1 from foo).
  • деякі мовні ідіоми популярні просто тому, що вони швидші; нормально їх використовувати, оскільки більшість вільних користувачів мови знайомі з ними. (ваш приклад - хороший приклад).

7

Що ви хочете оптимізувати?

  • Продуктивність програмного забезпечення?
  • Надійність?
  • Продуктивність програміста?
  • Задоволеності клієнтів?
  • Енергоефективність?
  • Технічне обслуговування?
  • Час на ринок?
  • Вартість?

"Оптимізація" не завжди означає змусити код працювати якомога швидше. Бувають випадки, коли важливий найшвидший спосіб зробити щось важливе, але це дійсно не все, що часто зустрічається в більшості кодів. Якщо користувачі не можуть помітити різницю між 50 і 100 мікросекундами, фактично немає різниці між двома кодами, які працюватимуть лише зрідка. Ось приклад:

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

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

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


1
+1 Не кажучи вже про те, що за останні кілька років мобільні пристрої знову стали сильно залежними від оптимізації коду. Комусь, хто не пише оптимізований код або принаймні вважає, що це може скласти час, щоб їх інтенсивний додаток для процесора безперебійно працював на мобільному пристрої.
Styler

+1 дуже подобається вашому списку можливих оптимізацій. Він використав збори / фортран
Боз

@Styler: не буде довго, поки на мобільних пристроях не буде чотирьохядерний процесор з ГБ пам’яті, у нас вже є двоядерні смартфони.
Лі Лі Райан

@Lie Ryan: так, це правда, але, як і більшість піонерів, їм довелося подорожувати в дерев'яних човнах;)
Styler

7

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

ЗАРАЗ , програміст повинен намагатися уникати дурних справ під час написання коду.

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

Ці речі легко досвідченому програмісту запам'ятати і майже завжди покращують якість коду.


Зрозумів, що мені потрібно бути чіткішим у редагуванні запитання, я говорив насправді те саме - я оновив його.
Боз

7

Вирішуючи, що оптимізувати, завжди пам’ятайте про закон Амдала . Дивіться посилання для точної математики; жалюгідне твердження, яке слід пам'ятати:

Якщо на одну частину вашої програми припадає 10% часу її виконання, а ви оптимізуєте її для запуску вдвічі швидше, програма в цілому прискориться лише на 5%.

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

Отже, що говорить закон Амдала про мікрооптимізацію? У ній сказано, що вони, можливо, того варті, якщо застосовуватимуться на всій основі. Якщо ви можете поголити один відсоток від часу виконання кожної функції у вашій програмі, вітаємо! Ви витратили програму на один відсоток. Чи варто було це робити? Ну, як хлопець-компілятор, я був би радий знайти оптимізацію, яка це зробила, але якщо ви це робите вручну, я б сказав, шукайте щось більше.


1
+1 за цитатою Amdahl, але я не згоден з "щоб вся програма працювала вдвічі швидше, вам потрібно пришвидшити кожен твір". Я б сказав, що ти насправді не прискорюєш жодної «частини». Швидше ви знайдете непотрібну роботу і усунете її. Особливо виклики функцій, якщо програма щось більше, ніж іграшка. Більшість поширених думок про продуктивність, здається, повністю ігнорують важливість пошуку цілих непотрібних гілок дерева викликів (які можуть бути окремими інструкціями) та їх вимкнення.
Майк Данлі

Чорт у слові "середній" є. Це математично випадок, щоб прискорити програму на 50% кожен шматок повинен бути прискорений на 50% в середньому . Тепер, якщо ви зможете розділити програму на роботу, яка займає 75% часу виконання, та іншу, яка займає 25%, і прискорити колишнє збільшення в 3 рази, це дасть вам загальну суму 50%, незважаючи на те, що ви нічого не зробили на останній роботі. Але набагато частішим випадком є ​​те, що є десятки «робочих місць», на які кожна займає менше 5% часу виконання - і тоді вам доведеться прискорити або позбутися багатьох з них.
zwol

Я думаю, що є ще більш поширений випадок. Там "робота" займає 50% часу, але вона вам насправді не потрібна , тому ви видаляєте її повністю, скорочуючи загальний час на цю суму, а потім повторюйте. Я знаю, що це важко прийняти - програми можуть витрачати великі частки часу, роблячи речі, які (заднім числом) зовсім непотрібні. Але ось мій канонічний приклад .
Майк Данлаве

6

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

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

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

  • Чи добре написаний код?
  • Чи програма може отримати доступ до своїх даних без проблем?
  • Чи можна використовувати кращий алгоритм?

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


5

Швидкість виконання - один із багатьох факторів, що сприяють якості програми. Часто швидкість має зворотну кореляцію з читабельністю / ремонтопридатністю. Майже у всіх випадках код повинен бути читабельним для людини, щоб код міг підтримуватися. Єдиний час, коли читабельність може бути порушена - це важлива вимога швидкості. Вимога зробити код швидше, ніж дозволяє повна читабельність / ремонтопридатність, навряд чи застосовна, але є певні випадки, коли це станеться. Головне пам’ятати, що мікрооптимізований код часто є хакі-кодом, тому, якщо десь немає визначеної вимоги, майже завжди це неправильний спосіб вирішити проблему. Наприклад, користувач майже ніколи не помітить різницю між .5 секундою та 1 секундою часу виконання операцій CRUD, тому вам не потрібно вступати в збори-interop-hackfest, щоб дістатися до цього .5 секунд. Так, я міг би літати на вертольоті на роботу, і це було б у 10 разів швидше, але я цього не роблю через ціну і те, що вертоліт набагато складніше літати.Коли мікрооптимізувати код без потреби, це саме те, що ви робите: додаючи непотрібну складність і вартість, щоб досягти зайвої мети.


5

Мікрооптимізація важлива, коли ви стикаєтесь із обмеженням. Те, що вам цікаво, може бути пам’яттю, пропускною здатністю, затримкою або енергоспоживанням. Зауважте, що це характеристики на рівні системи; вам не потрібно (і не може) оптимізувати кожну функцію всіляко.

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

Зауважте, що невеликі "вбудовані" системи сьогодні можуть бути досить близькими до Vaxen або PDP-11 минулого року, тому ці питання раніше були більш поширеними. У сучасній системі загального призначення, що здійснює сучасні загальні комерційні обчислення, мікрооптимізація зустрічається рідко. Це, мабуть, частина того, чому ваш батько займає посаду, яку він займає.

Однак не має значення, чи маєте ви справу з наносекундами, мілісекундами, секундами або годинами; питання однакові. Їх потрібно оцінювати в контексті системи та того, що ви намагаєтесь досягти.

Це приклад нещодавнього запитання, на яке я відповів на стек переповнення для випадку, коли необхідна мікрооптимізація: відеокодери з відкритим кодом для вбудованої системи .


4

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

Інша проблема залежить від конфігурації комп’ютера, іноді ваша мікрооптимізація може мати гірші результати, ніж без "оптимізації".

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

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

Я не кажу, що не робити мікрооптимізації - це привід для написання дурного коду.


4

Якщо ви почнете турбуватися про мілісекунди, вам слід подумати про те, щоб відмовитися від PHP і використовувати натомість C або Assembly. Не те, що я хотів би це зробити, просто немає сенсу обговорювати такі номери і використовувати мову сценаріїв. Ваш код повторюється з цією командою, що часто все одно?

Фактори навколишнього середовища тут не підлягають сумніву, ці сервери так чи інакше працюють 24/7, і якщо вони насправді щось обробляють, має значення лише те, чи справді це завдання виконується дуже довго.

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


+1 вимкнення світла або не відповідає на запитання.
Боз

4

Вам слід вибрати найкращий, простий алгоритм виконання завдання. Причина, яка повинна бути простою, полягає в тому, щоб зберегти код читабельним. Причина, по якій він повинен бути найкращим, полягає в тому, щоб уникнути початку з поганими характеристиками часу виконання. Не слід сліпо вибирати BubbleSort, коли знаєте, що у вас будуть великі набори даних. Однак це добре для випадкових сортів з 10 елементів.

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


BubbleSort насправді може бути кращим, ніж квакісорт або злиття, коли ваші дані майже відсортовані лише кількома бродячими елементами, що не за горами від їх кінцевого пункту призначення. Однак для всіх інших завдань слід використовувати вбудовану функцію сортування, яку надає вам ваша мова програмування; це найпростіший спосіб почати роботу (і вбудована функція сортування на більшості мов має хороші показники). СЛОВА порада: start out with bad runtime characteristicне свідомо починайте з поганої характеристики виконання.
Лі Лі Райан

@Lie, якщо ви ЗНАЄМО, що ваші дані майже відсортовані, і ви ТЕБЕ можете використовувати бульбашки, ви не точно сліпо вибираєте свій алгоритм ... Також дякую , що вказали на друкарську помилку.

4

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

До певного моменту код завжди може бути швидшим, ніж зараз. Якщо ви не збираєте вручну упаковку, маючи на увазі певний чіп, завжди можна щось отримати за допомогою оптимізації. Однак, якщо ви НЕ хочете скласти ручну збірку для всього, що ви робите, повинна бути кількісна мета, яка, як тільки ви зустрінетесь, ви скажете «цього достатньо» і перестаньте оптимізувати, навіть якщо все ще є вражаючий прихильник продуктивності тобі в обличчя.

Гарний, елегантний, надзвичайно виконавський код марний, якщо він не працює (а під "роботою" я маю на увазі отримання очікуваного результату з урахуванням усіх очікуваних вкладів). Тому створення коду, який працює, ЗАВЖДИ повинен бути першочерговим завданням. Після того, як це працює, ви оцінюєте ефективність, і якщо цього не вистачає, ви шукаєте способи його покращення, аж до того, де це досить добре.

Є кілька речей, які ви повинні вирішити наперед, які впливатимуть на ефективність; дуже основні рішення, наприклад, яку мову / час виконання ви будете використовувати для реалізації цього рішення. Багато з них вплинуть на продуктивність на багато порядків більше, ніж викликати один метод проти іншого. Чесно кажучи, PHP, як сценарій мови, вже є хітом для продуктивності, але оскільки в С / С ++ будується дуже мало скриптованих сайтів, це порівняно з іншими технологіями, які ви, швидше за все, виберете (Java Servlets, ASP.NET тощо).

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


2
+1 Створення коду, який працює, ЗАВЖДИ повинен бути першочерговим завданням.
Боз

2
@Keith, насправді Кнут сказав це першим, і він сказав трохи більше, ніж це.

"Зробіть це, а потім змусьте його працювати так швидко, як потрібно працювати", Анон.
Джон Сондерс

1
Насправді релігія є коренем усього зла, але я відступаю.
Томас Едінг

4

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

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


3

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


3

Важливо, якщо:

1) Життя когось залежить від вашого коду. Функція, яка займає 25 мс для виконання на чиємусь пульсометрії, мабуть, погана ідея.

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


2
Лише кілька незначних моментів у вашому прикладі: Функція в моніторі серцебиття, який займає 25 мс, не буде проблемою, доки інші необхідні завдання можуть відбуватися з необхідним часом відповіді. Перерви для цього хороші. І затримка в 25 мс на те, що лише відстежує реальні події, щоб оновити показ для споживання людиною, ймовірно, не є проблемою.
janm

3

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

Ні, враховуючи, що є такі платформи, як JVM та .NET, де код записується для віртуальної машини і, таким чином, намагаючись оптимізувати виконання, можливо, не вийде так добре, що оптимально на робочому столі розробника не обов’язково однакове на сервері. Подивіться, наскільки віддалені від апаратури деякі з цих програм високоякісного програмного забезпечення знаходяться ще тут. Що слід врахувати, враховуючи різноманітність обладнання, наскільки реально оптимізувати код для конкретних мікросхем, таких як процесор чи графічний процесор, коли нова модель, можливо, вийде менше ніж за рік?

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


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


1
Зауважте, що ви можете абсолютно робити мікрооптимізацію на таких платформах, як JVM та .NET, вони просто приймають дещо інші форми. Але те ж саме, якщо порівнювати і старий, простий компілятор C з більш сучасним, високооптимізуючим компілятором: оптимізації, які може зробити користувач, виглядатимуть інакше.
Йоахім Зауер

1

Я думаю, що велика різниця між хорошим програмуванням та мікрооптимізацією.

Якщо є два способи виконати одне і те ж завдання: один швидший, ніж інший, і обидва мають однакову читабельність, вам слід скористатися швидше. Завжди. І це добре програмування. Немає підстав не використовувати кращий алгоритм для вирішення проблеми. І навіть документувати це легко: дайте ім’я алгоритму, кожен зможе його переглянути в Google і знайти більше інформації про те, як він працює.

І хороші алгоритми вже оптимізовані. Вони будуть швидкими. Вони будуть маленькими. Вони використовуватимуть мінімально необхідну пам'ять.

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

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


1

Читання коду IMHO важливіше, ніж мікрооптимізація, оскільки в більшості випадків мікрооптимізація цього не варта.

Стаття про безглузді мікрооптимізації :

Як і більшість із нас, я втомився читати публікації в блозі про нечутливі мікрооптимізації, такі як заміна друку на ехо, ++ $ i на $ i ++ або подвійні цитати на одиничні лапки. Чому? Тому що 99,999999% часу, це не має значення. Чому? Оскільки в 99,99% часу вам краще встановити прискорювач PHP на зразок APC, або додати ці пропущені індекси в стовпці бази даних або спробувати уникнути тих 1000 запитів баз даних, які у вас є на домашній сторінці.

print використовує ще один опкод, оскільки він фактично щось повертає. Можна зробити висновок, що відлуння швидше, ніж друк. Але одна опкод нічого не коштує, насправді нічого.

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

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


1

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

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

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

  1. Ваші залежності від конкретної проблеми можуть змінитися, і будь-який час, витрачений на оптимізацію до заповнення логічного розділу вашої заявки, є марною тратою часу. Я маю на увазі оптимізацію на порівняно ранній стадії. Сьогодні у вас є, List<T>і до того часу, коли ваша програма додається, вам довелося її змінити, LinkedList<T>і тепер все тестування було марною витратою часу і сил.

  2. Переважно реальне вузьке місце вашої програми (читається як мірна різниця) може становити 5% вашого коду (в основному sql), а оптимізація інших 95% не дає вашим клієнтам ніякої користі.

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

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

Зокрема, до негативу поганої оптимізації є:

  1. Це не часто дає вам ефективність, яку ви очікуєте. Дивіться це запитання на SO, де оптимізація пішла не так . Насправді це може мати несприятливі наслідки. Ось у чому проблема з недокументованою поведінкою.

  2. Переважно сучасні компілятори зроблять це за вас все одно.

Наведу кілька прикладів поганої та доброї оптимізації:

Погане -

  1. використання менших цілих типів замість Int32.

  2. ++i використовується замість i++

  3. forзамість foreach(найгірше, що я бачив, повністю перемагає логіку)

  4. уникаючи закритих змінних

    string p;
    foreach (var item in collection)
        p = ...;
    
  5. використання charзамість рядка під час конкатенації рядків, наприклад:

    string me = 'i' + "me myself"; // something along that line - causes boxing
    

Добре (з .NET world. Повинно бути зрозумілим) -

  1. Подвійний пошук

    if (Dictionary<K, V>.TryGetValue(K, out V))
        do something with V
    

    замість

    if (Dictionary<K, V>.ContainsKey(K))
        do something with Dictionary<K, V>[K]
    
  2. Завантажте їх усіх

    DirectoryInfo.EnumerateFiles();
    

    замість

    DirectoryInfo.GetFiles();
    
  3. Двоступеневий кастинг:

    s = o as string;
    if (s != null)
        proceed
    

    замість

    if (o is string)
        s = (string)o;
    
  4. Якщо замовлення не має значення

    if (counter < X || expensiveFunction())
    

    замість

    if (expensiveFunction() || counter < X)
    
  5. Бокс

    void M<T>(T o) //avoids boxing
    {
    
    }
    

    замість

    void M(object o)
    {
    
    }
    

Якщо ви запитаєте мене, чи дають вони помітні переваги від продуктивності, я б сказав «ні». Але я б запропонував використовувати їх, оскільки це випливає з розуміння поведінки цих конструкцій. Навіщо робити два дзвінки, коли ви можете зробити лише 1? З філософської точки зору, її хороша практика кодування. І 1 і 3 трохи менш читаються занадто строго, але чи вони козирять читабельність? Ні, не багато, тому я використовую. Тепер це головне - підтримання гідного співвідношення продуктивності та читабельності. І коли це, то про те, де ви прорисуєте лінію.


1

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

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

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

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

Мені не так давно вдалося скоротити операцію вниз з 24 секунд до 25 мілісекунд (приблизно в 960 разів швидше), з однаковими виходами (захищеними автоматизованими тестами), без зміни алгоритмічної складності, для об'ємного розсіювання теплової дифузії через "мікрооптимізація" (найбільша з яких відбулася через зміну компонування пам'яті, яка зменшила її приблизно на 2 секунди, потім решта - речі на зразок SIMD та подальший аналіз пропусків кеша у VTune та деяка подальша перестановка компонування пам'яті).

Вулфір пояснює тут техніку, і він боровся з необхідним часом: http://blog.wolfire.com/2009/11/volumetric-heat-diffusion-skinning/

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

Після того, як я "мікро-оптимізував" його з 24 секунд до 25 мс, це змінило гру в робочому процесі. Тепер артисти можуть змінювати свої установки в режимі реального часу зі швидкістю понад 30 кадрів в секунду, не чекаючи 24 секунди кожен раз, коли вони вносять невеликі зміни до своєї установки. І це фактично змінило весь дизайн мого програмного забезпечення, оскільки мені більше не потрібна смуга прогресу та подібні речі, вони просто стали інтерактивними. Тож це може бути "мікрооптимізація" в тому сенсі, що всі поліпшення відбулися без будь-якого поліпшення алгоритмічної складності, але саме "мегаоптимізація" фактично зробила те, що раніше було болючим, неінтерактивним процесом в інтерактивний, який повністю змінив спосіб роботи користувачів.

Вимірювання, вимоги до кінця користувача, контекст

Мені дуже сподобався коментар Роберта тут, і, можливо, я не зміг зробити точку, яку я хотів:

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

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

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

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


2
Ну, давай. Ніхто не збирається заперечувати, що подібні зміни не «варті». Ви змогли продемонструвати відчутну користь; багато так званих мікрооптимізацій не можуть.
Роберт Харві

1
@RobertHarvey Це був свого роду точкою я сподівався зробити, так що деякі люди називають «мікро-оптимізації» не обов'язково мікроскопічний ефект, але це так сильно залежить від контексту, вимірювання і т.д. issetпроти strlenздається більш мізерну у фокусі відсутні контекст і вимірювання. :-D
енергія Дракона

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

1
Деякі оптимізації зумовлюються нагальною потребою, а інші - цікавістю (інтелектуальною гонитвою та авантюризмом). Нам потрібно і те, і інше. У історії Dragon Energy це, мабуть, не було "нагальною потребою", оскільки художники, мабуть, не голосно скаржилися на те, що не бачили жодних результатів візуалізації до 24 секунд після кожного редагування. Насправді користувачі можуть не знати, наскільки швидко це могло бути, поки програміст не вклав усіх зусиль, щоб побити рекорд швидкості. Обмежувати себе спонуканим попитом має сенс для бізнесу, але при цьому буде упущено кілька дивовижних можливостей оптимізації чи змінних ігор.
rwong

1
Говорячи про діловий сенс, існує також питання монетизації. Кожен крок (наприклад, програміст, який працює над оптимізацією продуктивності) коштує грошей, а витрати потрібно компенсувати, щоб мати сенс для бізнесу. Таким чином, потрібно запитати, чи можна «продати» поліпшення швидкості, що змінюється в грі, або скільки грошей буде «заощаджено», якщо програміст повинен отримати схвалення від бізнес-менеджера.
rwong

0

Я кажу так - мікрооптимізація - це процес оптимізації чогось, що зовсім не є вузьким місцем. Наприклад, якщо ваша програма викликає дві функції A і B, а A займає 100 мілісекунд, а B займає 2 мікросекунди, а ви продовжуєте оптимізувати функцію B. Це не тільки важливо, це абсолютно неправильно. Але оптимізація функції B називається оптимізацією, а не мікрооптимізацією. Важливість оптимізації залежить. Скажіть, що вам більше нічого не потрібно робити, і ваша програма без помилок, тоді так, це важливо. Але загалом у вас є пріоритети. Скажімо, вам потрібно додати / записати функцію C. Якщо ви думаєте, що функція запису C принесе вам більше грошей, ніж швидше зробить вашу програму без цієї функціональності, тоді йдіть на оптимізацію. В іншому випадку переслідуйте функціональність. Також, досвідчені програмісти, орієнтовані на продуктивність, не витрачають багато часу на оптимізацію, вони просто пишуть швидкі програми. Принаймні вони знають, якими інструментами користуватися, а що не витрачати на роки, роблячи безглузді (читайте мікро) оптимізації.


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