Чому так рано погано оптимізувати?


168

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

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

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

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


Коментарі не для розширеного обговорення; ця розмова переміщена до чату .
Джош

3
Відповісти на це не могло бути простіше: "він витрачає час". Ви також можете запитати: "навіщо намагатися економити гроші під час покупки?"
Fattie

27
І навпаки, зауважте, що багато інженерів доволі просто говорять, що речення "не оптимізуйте занадто рано" просто неправильно . Пропозиція має бути просто "не оптимізуйте, поки не знаєте, що оптимізувати". Отже, досить просто, якщо є три системи A, B і C, це абсолютно безглуздо оптимізувати A, якщо, виявляється, A зовсім не є вузьким місцем, а C - насправді вузьким місцем. У цьому прикладі, очевидно, оптимізація A була б зовсім марною тратою часу. Отже - досить просто - не оптимізуйте, поки не дізнаєтеся, який з A, BC оптимізувати: це все, що це означає, це все так просто.
Fattie

2
Оптимізація часового класу вашої програми під час розробки дуже відрізняється від спроби розчесати кілька інструкцій із циклу, який зазвичай є постійним часом. Зосередьтеся на O (n) vs O (n log n), а не "написання циклу таким чином економить одну інструкцію CPU".

1
@phyrfox Насправді скорочення часу завантаження мені здається більш вражаючим. Час завантаження три секунди помітний. Я не впевнений, помітні від 55 кадрів до 60 кадрів в секунду.
іммібіс

Відповіді:


237

Преамбула:

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

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

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

Це означає, що при сумнівах ми повинні:

  • Віддайте перевагу коду, який простий у написанні, зрозумілий для розуміння та легкий для зміни для початку

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

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

  • Архітектурні рішення структурувати ваш код таким чином, щоб відповідати вашим потребам - вибір відповідних модулів / обов'язків / інтерфейсів / комунікаційних систем розглянутим способом.

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

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

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

Отож, з цим з’ясуємо, чому ми можемо вважати цю політику корисною саме в іграх:


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

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

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

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

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

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

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

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


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

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

1
@Baldrickk Я б сказав, що варто поділитися як додаткова відповідь. (Я б підтримав це!) Моя відповідь пропускає важливість архітектури та планування, щоб уникнути створення великих проблем в першу чергу. Що стосується посилання Gizmo на "розробку програми взагалі", то звідси походить ця концепція передчасної оптимізації. Як зазначено вище, неправильна оптимізація може стати технічною заборгованістю так само легко, як і відсутність оптимізації. Але ми повинні підкреслити, що ми ніколи не робимо справи навмисно повільно, просто віддаємо перевагу простоті та розбірливості, поки не зможемо
проаналізувати

1
Хоча я, мабуть, найбільше недосвідчений з вас, я мушу сказати, що я вважаю цей "передчасний оптимізаційний корінь всього зла" трохи дивним. Два роки тому я намагався щось зробити в Unity3D. Я написав кілька запитів LINQ, кожен з яких використовував попередній. Я подивився на свій код і почав сильно сумніватися. Я думав, складність обчислень жахлива. Я взяв аркуш паперу і підрахував, що обробка цих запитів на очікуваному розмірі даних займе години. Тому я додав трохи кешування тут і там. І запити працювали нормально.
гаазкам

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

42

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

"Чи не було б неймовірно складно змінити деякі основні структури гри наприкінці, а не розвивати їх вперше з врахуванням продуктивності?"

Це, на мій погляд, суть питання.

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

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

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

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

Параметри:

  • Купуйте другий пором (паралельна обробка)
  • Додайте ще одну палубу автомобіля на паром (стиснення руху)
  • Оновіть двигун пором, щоб зробити його швидшим (переписані алгоритми обробки)

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

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

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

tl; dr:

  • Спробуйте в першу чергу розробити ефективність.
  • Якщо вам запропоновано два варіанти, ви виберете більш ефективний.
  • Напишіть свій код якомога модульніше з чітко визначеними інтерфейсами.

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


16
На початку ви також можете реалізувати свій пором як IRiverCrossing, і коли стане зрозуміло, що об'єм трафіку занадто великий для встановлення парома, застосуйте міст як IRiverCrossingі відпустіть його. Трюком, звичайно, є зменшення зовнішнього API Ferry. і міст до загальної функціональності, щоб вони могли бути представлені тим самим інтерфейсом.
Містер Міндор

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

2
Дуже приємний приклад того, чому OOP так важливий в наші дні.
Хайме Галлего

1
Ви потрапили в правильну причину. Мантра Дональда Кнута справедлива лише тоді, коли швидкість не є однією з основних вимог, і орієнтація на оптимізацію поставить під загрозу основний дизайн. На жаль, швидкість гри в іграх часто лежить в основі, а значить, її слід враховувати в дизайні на початку. Занепокоєння ОП (і ваша відповідь) цілком виправдано.
Пітер А. Шнайдер

3
@AlexandreVaillancourt замість того, щоб відповідати заголовку питання, я спробував відповісти на те, що, на мою думку, є ключовою частиною питання, що насправді відповідає; тобто "чому я не повинен оптимізувати рано, якщо оптимізація піде набагато більше роботи пізніше, тому що моя конструкція виправлена" (перефразовано) . Ця відповідь також почалася як коментар до відповіді DMGregory, і є доповненням до неї, і не багато сенсу дублювати його відповідь.
Балдрік

24

"Не оптимізуйте рано" не означає "вибрати найгірший можливий спосіб робити речі". Ви все ще повинні врахувати наслідки для продуктивності (якщо ви не просто прототипуєте). Справа не в каліцтві інших, більш важливих речей на даному етапі розвитку - таких як гнучкість, надійність і т.д. слідкувати за витратами. Чи варто використовувати сильний набір тексту? Більшість ігор добре працювали; скільки б вам коштувало це зняти, якби ви знайшли цікаві можливості використання гнучкості для гри?

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

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

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

Тепер розглянемо гру, яку, можливо, ви хочете зробити. Чи справді є якесь технологічне диво, яке робить або порушує цю гру? Можливо, ви передбачаєте гру відкритого світу про нескінченний світ. Це справді центральна частина гри? Чи гра без нього просто не працюватиме? Можливо, ви думаєте про гру, де місцевість деформується без обмежень, з реалістичною геологією і подібною; чи можете ви змусити його працювати з меншим розмахом? Він би працював у 2D замість 3D? Отримайте щось веселе якнайшвидше - навіть якщо оптимізація може зажадати від вас переробити величезний фрагмент наявного коду, можливо, це варто того; і ви навіть можете усвідомити, що збільшення речі насправді не робить гру кращою.

Як приклад нещодавньої гри з великою кількістю оптимізацій, я назначу Factorio. Однією з важливих частин гри є ремені - їх багато тисяч, і вони несуть безліч окремих шматочків матеріалів по всій фабриці. Чи розпочалася гра з сильно оптимізованим ремінним двигуном? Немає! Насправді оригінальну конструкцію пояса неможливо було оптимізувати - вона на зразок фізичного моделювання предметів на поясі, що створило кілька цікавих речей, які ви могли зробити (саме таким чином ви отримуєте "виникаючий" геймплей - геймплей, який дивує дизайнер), але означало, що вам доведеться моделювати кожен предмет на поясі. З тисячами ременів ви отримуєте десятки тисяч фізично модельованих предметів - навіть просто видалення цього та надання ременів виконувати роботу дозволяє скоротити пов'язаний час процесора на 95-99%, навіть не враховуючи таких речей, як локальність пам'яті. Але це корисно робити лише тоді, коли ви дійсно досягнете цих меж.

Практично все, що мало відношення до ременів, потрібно було переробити, щоб оптимізувати пояси. І ремені потрібно було оптимізувати, адже вам потрібно було багато ременів для великої фабрики, а великі фабрики - одна привабливість гри. Зрештою, якщо ви не можете мати великі заводи, навіщо мати нескінченний світ? Смішно запитати - ранні версії не виходили :) Гра перероблялася та перероблялася протягом багатьох разів, щоб знайти там, де вони є зараз, - включаючи 100% ремейк, коли зрозуміли, що Java - це не шлях до така гра і перейшла на C ++. І це спрацювало чудово для Факторио (хоча це все-таки добре, що його не оптимізували з початку роботи - тим більше, що це був проект хобі, який, можливо, просто не вдався б інакше через відсутність інтересу).

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

Нарешті, у вас чудова, весела гра. Чи є сенс оптимізувати зараз ? Га! Це все ще не так зрозуміло, як ви могли подумати. Чи є щось веселе?ви можете зробити замість цього? Не забувайте, що ваш час все ще обмежений. Все вимагає зусиль, і ви хочете зосередити це на тому, де це найбільше важливо. Так, навіть якщо ви робите "безкоштовну гру" або гру з відкритим кодом. Дивіться, як грається гра; зауважте, де вистава стає вузьким місцем. Чи оптимізація цих місць робить для себе більше задоволення (як будівництво все більших, все більш заплутаних заводів)? Чи дозволяє вам залучати більше гравців (наприклад, із слабшими комп'ютерами або на різних платформах)? Завжди потрібно розставляти пріоритети - шукайте коефіцієнт зусиль та врожайності. Ви, ймовірно, знайдете велику кількість низько висячих фруктів лише від того, щоб грати у свою гру і спостерігати, як інші грають у цю гру. Але зауважте важливу частину - щоб потрапити туди, вам потрібна гра . Зосередьтеся на цьому.

Як вишня зверху, вважайте, що оптимізація ніколи не закінчується. Це не завдання з невеликою галочкою, яку ви закінчите та переходите до інших завдань. Завжди можна зробити «ще одну оптимізацію», і велика частина будь-якої розробки - це розуміння пріоритетів. Ви не здійснюєте оптимізацію заради оптимізації - ви робите це для досягнення певної мети (наприклад, "200 одиниць на екрані одразу на 333 МГц Пентію" - чудова мета). Не втрачайте слідів кінцевої мети лише тому, що ви занадто сильно зосереджуєтесь на проміжних цілях, які вже навіть не можуть бути передумовою для кінцевої цілі.


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

2
@immibis Рівно. Зробити це краще, ніж люди фактично досягли меж, це буде марною тратою ресурсів, які краще витратити в іншому місці. Навіть з останніми оптимізаціями ви, швидше за все, зіткнетеся з проблемою лише для мегафабрик, що виходять за рамки звичайного ігрового процесу (запуск ракети). Але це ввімкнуло нові налаштування геймплею Marathon, які потребують набагато більш важкої логістики. І знову вони визначили вузькі місця, отримавши статистику від людей, які насправді грають у цю гру - приблизно половина вузьких місць була для них великим сюрпризом.
Луань

@Fattie Отже, ви розумієте питання, але не відповідь? Ви просто намагаєтесь сказати, що можлива простіша відповідь (наприклад, "Економіка")? Я не бачу, як ваш коментар повинен бути конструктивним.
Луань

2
@Fattie Якщо ви вважаєте, що відповідь "Оптимізуйте лише коли ви дізнаєтесь, що таке вузьке місце", опублікуйте це як відповідь. Ви вже витратили набагато більше слів, ніж потрібно для хорошої відповіді, тому продовжуйте. Яка оптимізація не робить речі кращими та гіршими? Я, звичайно, жодного разу не бачив. Основне, на що я повторюю, полягає в тому, що це завжди вигідний час, який можна краще провести в іншому місці, складність, що обмежує вашу гнучкість ... У прикладах зазначається, що "рано" не є абсолютним терміном; деякі оптимізації необхідні з першого дня, а інші - згубні.
Луань

1
@Fattie "Оптимізуйте лише після того, як ви дізнаєтесь, що таке вузьке місце", - це відповідь "Коли я повинен оптимізувати?" і це не відповідь на "Чому так рано погано оптимізувати?".
іммібіс

10

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

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

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

введіть тут опис зображення

Потім ми переходимо до створення нашого першого шару / модуля гри так.

введіть тут опис зображення

Рухаючись далі, ми будуємо наш другий шар / модуль.

введіть тут опис зображення

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

введіть тут опис зображення

Ідеально, тепер додаток повністю використовує доступні нам ресурси, додаток краще, добре?

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

Ми шукаємо альтернативу, знаходимо її, і врешті-решт, це також вимагає від нас змінити 2-й модуль нашої програми, оскільки він несумісний з нашим нещодавно вибраним 3-м модулем. (На щастя, він дещо сумісний з нашим 1-м модулем, тому нам не доведеться переписувати все з нуля.)

Тож ми все це склали ...

введіть тут опис зображення

Хм, ти бачиш, що сталося?

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

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

введіть тут опис зображення

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

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

введіть тут опис зображення

А тепер, якщо в цей момент ми виконаємо оптимізацію, ми отримаємо щось задоволення.

введіть тут опис зображення

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


3
Я знімаю рекламу. Нам не байдуже, як ви робили зображення; єдина важлива частина - припущення, що ви маєте право розміщувати їх.
Gnemlock

2
@Gnemlock досить справедливо, хоча мій намір не був спрямований на рекламу, я також бачу, як це можна легко неправильно трактувати як таке, і я погоджусь, що він нічого не додає у відповідь, тому йому немає місця в ньому.
Стеля Гекко

2
Я думаю, що ця візуальна метафора є надзвичайно ефективною. Чудовий підхід до відповіді на питання! :)
DMGregory

8

Гроші.

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

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

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

* Інші відповіді досить добре виділили частину часу


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

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


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

3
@JBentley Розгляньте це як доповнення до відповіді DMGregory.
Олександр Вейланкорт

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

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

6

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

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

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

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

Зробіть це першим. Потім затягніть мотузки.


2
Я думаю, що "ефективність" - це не слово, яке ви збираєтеся, це означає "здатність створювати ефект", тому в певному сенсі оптимізація - це все щодо підвищення ефективності. Ви збираєтесь отримати якусь конкретну версію ефективності? (Чи можете ви зв’язатись із цим?) Ви натомість маєте на увазі щось на кшталт гнучкості?
doppelgreener

2
@doppelgreener Це означає, що ви зробите рішення більш ефективним, поки воно не перестане створювати ефекти, які ви хочете ...
immibis

1
"Зробіть спочатку роботу. Потім затягніть мотузки". - Це повинно коштувати стільки, скільки решта відповіді разом. І не сказати, що інші речі були недобрі.
ebyrob

1
@ebyrob: є ще одна приказка: "Зробіть це, зробіть це правильно, зробіть це швидким" wiki.c2.com/?MakeItWorkMakeItRightMakeItFast
ninjalj

@ninjalj Це теж добре. Звичайно, мій начальник завжди мені каже: "Не поспішайте, зробіть це правильно". Тож я не знаю, чи є те, що ви говорите, настільки універсальне, як головне, про яке оригінальний плакат вимагає більш детальної інформації.
ebyrob

2

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

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

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

Отже, я б сказав, що добре, з точки зору досвіду навчання, кілька разів оптимізувати: p


2

Оптимізація зосереджена на тому, щоб комп'ютер працював найкраще над кодом, тоді як розробка вимагає, щоб програміст найкраще працював над кодом.

Оптимізація не дає зрозуміти. Це змушує роботу комп'ютера менше, а програміста більше.

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


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

Ідеальна відповідь на тавтологічне запитання.
Fattie

2

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

Наприклад, якщо у вас є алгоритм маршрутизації A *, чи не було б краще написати його найбільш оптимальним способом? Замість того, щоб пізніше змінити половину коду, який у вас є, тому що вам довелося внести деякі зміни в алгоритм, тому що тепер потрібен інший метод викликів та зворотних викликів? І якщо у вас вже є оптимізований код з самого початку, це заощадить вам багато часу. Оскільки ви можете скласти відносини між об'єктами та їх взаємодією, замість того, щоб сліпо створювати тони нових сценаріїв і робити всі з'єднання відразу - це призводить до незрозумілого коду sphagetti.

Останнє, що я хочу додати, це те, що пізніше, навіть якщо ви більше не хочете робити гру, у вас є оптимізований алгоритм A *, який ви можете використовувати для своїх наступних ігор. Багаторазовість. Наприклад, у багатьох іграх є інвентар, пошук маршрутів, генерація процедур, взаємодія між npc, бойовою системою, AI, взаємодія інтерфейсів, управління введеннями. Тепер слід запитати себе - "Скільки разів я переписав ці елементи з нуля?" Вони складають 70-80% гри. Вам справді потрібно весь час їх переписувати? А що робити, якщо вони неоптимізовані?


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

@gmatht Ну * * може бути різним, як я вже сказав, він може мати поганий дизайн і не дуже добре працювати. Але це може бути багатопотокове, засноване на купі Фібоначчі, мати деякі передбачення, розбиті на шматки. Якщо ми говоримо про пошук маршруту, ми можемо додати поле Flow для змішування з A *. Також спосіб згладжування, мультирост. Можливо, A * - не найкращий приклад, але, як я вже сказав, оптимізація не має нічого спільного з фактичним зміною коду, розробник змінює код, оскільки він був погано розроблений, наприклад, він не дотримувався SOLID як 1 причину. Якщо ви написали це A * добре, вам більше не потрібно писати.
Відвертий Місяць _Max_

Мікрооптимізація @gmatht насправді не є проблемою. Я думаю, що ОП означає більше кращий та найефективніший спосіб обчислення поведінки ШІ або шейдера чи будь-чого іншого.
Відвертий Місяць _Max_

Якщо ви знаєте, як правильно написати це, я не бачу проблеми в цьому. Це займе стільки ж часу або навіть менше. Це більше залежить від досвіду розробників. Як програміст, якби я знав краще рішення, я б не писав лайно. Якщо я знаю, як написати купу Фібоначчі, я не буду використовувати List і сортування для отримання значень min або max. Звичайно, знадобиться ще трохи часу і зусиль, щоб написати це, замість того, щоб використовувати List.Sort (); , але що робити, якщо я вже маю багаторазовий використання?
Відвертий Місяць _Max_

2
@CandidMoon Я не погоджуюся з "Це займе стільки ж часу або навіть менше". написати ефективний код. Можливо, знадобиться той самий час, щоб написати код, який не є явно неефективним, але коли ваше поняття "efficienct" означає розглянути питання про суперечність кешу, додавши багатопотоковість, використовуючи специфічні CPU властивості, доступні лише для деяких процесорів, перемикаючи алгоритми для великих N через O (N log N) vs O (N) - така річ є важкою та схильною до помилок і потребує набагато більше часу, ніж проста реалізація. Ви робите це лише тоді, коли знаєте, що це істотно вплине на кінцевий результат.
Майкл Андерсон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.