У чому сенс правила 90/10 оптимізації програми?


67

Згідно з Вікіпедією, правило 90/10 для оптимізації програми зазначає, що "90% часу на виконання програми витрачається на виконання 10% коду" (див. Другий параграф тут ).

Я справді цього не розумію. Що саме це означає? Як 90% часу на виконання може бути витрачено лише на виконання 10% коду? А як тоді з іншими 90% коду? Як їх можна виконати лише за 10% часу?


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

147
Зачекайте, поки ви почуєте правило 90/10 щодо тривалості проекту програмного забезпечення: "90% проекту займе перші 90% відведеного часу; останні 10% проекту займуть інші 90% відведеного часу ».
Пол Д. Уейт,

3
Плутанина тут: "час проводиться на виконання". Розглянемо a++; for(i=0;i<100;i++){b++;} for(i=0;i<100;i++){print(xyz);}. Звичайно, перший for-цикл витрачає набагато більше, ніж перший оператор, але другий for-loop витрачає ~ 1000x більше часу, ніж перший for-цикл, але не виконує . Він витрачає його на очікування друку . Отже, існує різниця між часом, витраченим на виконання , і часом, за який відповідає код .
Майк Данлаве

32
@ Paul_D._Waite Я подумав, що 90% проекту займає 90% часу, 90% того, що залишилося, займає ще 90% часу, і так далі вниз неконвергентної серії до висновку, що жоден проект не є коли-небудь закінчена або повністю виправлена ​​помилка за менш, ніж нескінченний час.
nigel222

9
Для практичних прикладів кілька кодів, над якими я працював (наукові моделі), використовували велику кількість коду (~ 10 К рядків) для читання та налаштування моделі, потім зробили цикл через кілька сотень рядків, щоб зробити фактичні обчислення. Але цей короткий цикл був n ^ 4 (три розміри простору, повторені через багато тисяч кроків часу), тому для обчислення потрібні були дні. Тож фактичне співвідношення було, мабуть, більше схожим на 99% / 1% :-)
jamesqf

Відповіді:


184

Тут грають два основні принципи:

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

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

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

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

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

5
Думаю, вам потрібно додати посилання на shouldioptimize.com :)
Іван Колмичек

13
Я думаю, що 90/10 походить від відомого принципу Парето 80/20 en.wikipedia.org/wiki/Pareto_principle
fernando.reyes

2
@StarWeaver Ось чому мови, які роблять написання надефективних сортів простішими, легшими або легшими, ніж хитрі сортування міхурів, є важливими там, як C ++. Такі «попередньо упаковані» алгоритми та код можуть бути дуже оптимізовані, не викликаючи складності в точці використання.
Якк

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

21

Це не закон природи, а правило, народжене великим досвідом. Це також відоме як правило 80/20 і є лише колись приблизним наближенням.

Петлі, гілки та інше управління потоком.

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

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

Як приклад розглянемо:

def DoSomeWork():
    for i in range(1000000):
        DoWork(i)
    except WorkExeption:
        print("Oh No!")

Тут print("Oh No!")воля буде виконуватись максимум один раз, а часто ніколи, тоді як DoWork(i)воля відбудеться приблизно мільйон разів.


7
Називаючи це правилом 80/20, може виникнути плутанина з принципом Парето , який застосовується ширше, ніж просто для програмування. Можливо, 90 і 10 - це просто зручні числа, які не мають цього значення в перекритті.
трихоплакс

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

2
Існує математична основа розколу 80/20 за принципом Парето. Вони не просто якісь уявні фігури, які представляють "багато" та "мало".
Мойлі

1
@Moyli - Так, "Існує математична основа для розколу 80/20 ...", але в реальному світі це ніколи (нормально, за збігом обставин, рідко) буде рівно 80/20.
Кевін Феган

2
@trichoplax принцип парето тут дуже добре застосовується. 20% причин (рядки коду) викликає 80% ефектів (час виконання)
njzk2

16

Петлі.

Я спокусився зупинитися на цьому! :-)

Розглянемо цю програму

1. do_something

2. loop 10 times
3.    do_another_thing

4.    loop 5 times
5.        do_more_stuff

Рядок 1 виконується один раз, а рядок 3 - 10 разів. Дивлячись по черзі на кожен рядок

1 1   0.8%
2 10  8.3%
3 10  8.3%
4 50 41.3%
5 50 41.3%

На два рядки припадає 83% часу виконання (якщо запустити, що всі рядки займають приблизно однаковий час. Отже, 40% програми займає> 80%.

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

Правило 90/10 (або як це іноді ставиться 80/20) - це "велике правило" - лише приблизно так.

Див. Також Принцип Парето


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

+1 для посилання на принцип Парето. Більш поглиблене пояснення можна побачити у цьому фантастичному відео "Vsauce" .
Раду Мурзеа

5

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

int main() {
    sleep(90); // approximately 10% of the program.
    // other 90% of the program:
    sleep(1);
    sleep(1);
    sleep(1);
    sleep(1);
    sleep(1);
    sleep(1);
    sleep(1);
    sleep(1);
    sleep(1);
    sleep(1);
    return 0;
}

Якщо бути трохи серйознішим, це означає, що в реальному коді ви майже завжди викликаєте важку функцію в циклі (замість sleep(90);), а решту 10% часу виконуєте деякі розрахунки з одним проходом.

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


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

3

Міркування 90/10 означає, що невелика частина вашого коду буде повторена або використана більше, ніж інші. Це часто використовується, щоб припустити, що ви повинні зосередити 90% своїх зусиль на розробці / оптимізації в цьому 10% свого коду.

Подумайте про звичайний текстовий процесор, як-от Microsoft Word або OpenOffice :

  • Діалог налаштувань використовується мало;
  • Підпрограми, які малюють символи, використовуються постійно.

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


6
Якщо Microsoft Word простий, що є прикладом складного?
Пітер Мортенсен

@PeterMortensen це не має сенсу.
Велика качка

@PeterMortensen Emacs, очевидно.
муру

2

Уявіть собі таку програму:

print "H"
print "e"
print "l"
print "l"
print "o"
for i=0 to 1,000,000
    print "How long now?"
next
print "B"
print "y"
print "e"

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


0

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

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


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

@PeterMortensen "вирішальне, але не часто" не те саме, що "повторно використовуватися майже кожну секунду і потрібно бути якомога швидшим"
Велика качка

@TheGreatDuck, і я не думаю, що це він мав на увазі. Тому що ви можете мати код, який виконується нечасто, але ви хочете, щоб це відбувалося якнайшвидше. Для прикладу візьмемо відновлення помилок - залежно від програми, може знадобитися певний час (5 хвилин, година, а може й більше), щоб система знову запрацювала. Однак, якщо, скажімо, система польоту натрапила на помилку, ви дійсно хочете, щоб вона була максимально швидкою. Тому що, якщо цього не відбудеться, він "знизиться" і "впаде" в дуже буквальному сенсі.
ВЛАЗ

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

@vlaz це правда, але річ у тому, що в літаку .... ВСЕ потрібно швидко бігти.
Велика качка

0

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

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


Це законна річ, яку люди використовують як правило.
Велика качка

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

Якщо ви насправді читаєте статтю у Вікіпедії, то побачите, що цитата, на яку посилається запитувач, має це цитування: amazon.com/Every-Computer-Performance-Book-Computers/dp/… Я особисто ніколи не бачив її в користуванні, але ви на пошту натрапили на мій погляд як грубий і недоброзичливий, тому я відповів. Очевидно 10% - це число, яке хтось склав. Я можу зробити його скільки завгодно бажаним, зробивши свою програму неефективною. Однак, чи це термін, який використовується в інженерії програмного забезпечення, очевидно, не можна обговорювати, оскільки багато людей тут погоджуються на його існування.
Велика качка

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

1
@BradThomas: Доказом проти теорії про те, що правило 90-10 винайшов хтось, хто редагував Вікіпедію, - це те, що воно широко цитувалося, з цифрами 90 і 10, за багато років до існування Вікіпедії; справжній принцип полягає не в тому, що саме на 10% коду припадає 90% часу виконання, а в тому, що в більшості програм на невелику частину коду - 10% або менше припадає така велика частина часу виконання - -90% або більше, що навіть 10% -ве поліпшення продуктивності цієї невеликої частини коду скоротило б загальний час виконання більш ніж на 1000-кратне покращення у всьому іншому.
supercat

0

Це переосмислення "принципу Парето", який стверджує, що "для багатьох подій приблизно 80% наслідків походять від 20% причин". Також відоме як правило 80/20. Це правило в основному застосовується до економіки, тому має сенс, що воно буде призначене для програмування.

Це просто закономірність, яку спостерігали протягом тривалого періоду часу.

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

https://www.youtube.com/watch?v=fCn8zs912OE&ab_channel=Vsauce

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