В чем смысл правила оптимизации программы 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 тратит в ~ 1000 раз больше времени, чем первый цикл 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
Особо следует отметить, что с такими вещами, как функции сортировки, гораздо быстрее (во время разработки) и проще сделать глупый простой алгоритм, который делает правильную вещь во всех случаях, чем получить элегантный алгоритм, полностью функциональный и без ошибок. (То есть единственные причины для написания своего рода алгоритма вне acadamea - это если вы создаете библиотеку или работаете на платформе без
таковой

5
Я думаю, что вам нужно добавить ссылку на shouldioptimize.com :)
Иван Колмычек

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

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

6
@IvanKolmychek Этот сайт вводит в заблуждение. Конечно, такой анализ затрат является одним из факторов, который необходимо учитывать, но есть и другие факторы, такие как пользовательский опыт. Вы можете сэкономить много денег, не оптимизируя, но вы также можете упустить большой доход, если люди покинут ваш сайт разочарованными.
jpmc26

20

Это не закон природы, а правило большого пальца, основанное на большом опыте. Это также известно как правило 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
Это пример принципа Парето. Обе пары чисел одинаково произвольны
Caleth

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% времени будет потрачено на выполнение крошечной доли кода - максимум 10%. Очевидно, что было бы возможно иметь программы, в которых все части тратят примерно одинаковое количество времени на выполнение, но это редко.
суперкат

+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% времени вы выполняете некоторые однопроходные вычисления.

Другой пример - обработка ошибок в некоторых сервисах высокой доступности. Любой высокодоступный сервис предназначен для работы неограниченное количество времени в нормальных условиях. Обычно он работает 99% времени, но иногда, в случае ошибки, он выполняет некоторую обработку ошибок и восстановление, которые могут быть даже более логически сложными, чем сама служба.


Хорошо, я надеялся, что кто-то опубликует этот экстремальный пример, который ясно показывает разницу.
Джечлин

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

В дополнение к зацикливанию, как уже упоминалось в других замечательных ответах, есть еще и принципы СУХОГО. Хорошо написанный, объектно-ориентированный код имеет много повторно используемых частей. Те части, которые повторно используются, по определению, используются как минимум в два раза чаще, чем то, что выполняется только один раз. Если у вас много ОО-кода, вы можете многократно использовать несколько классов и методов, а несколько других частей кода - только один раз.

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


2
Вы можете повторно использовать много кода, но все это может выполняться нечасто (хотя все еще важно).
Питер Мортенсен

@PeterMortensen «важно, но не часто» - это не то же самое, что «повторное использование почти каждую секунду, и нужно быть как можно быстрее»
Великая утка

@TheGreatDuck и я не думаю, что он имел в виду. Потому что вы можете иметь код, который выполняется нечасто, но вы хотите, чтобы он выполнялся как можно быстрее. Например, давайте возьмем исправление ошибок - в зависимости от приложения может потребоваться некоторое время (5 минут, час, возможно, больше), чтобы система снова заработала. Однако, если, скажем, система полетов обнаруживает ошибку, вы действительно хотите устранить ее как можно быстрее. Потому что, если этого не произойдет, он «упадет» и «рухнет» в буквальном смысле.
ВЛАЗ

Это, кажется, подразумевает, что DRY требует OO, что, конечно, не соответствует действительности. Повторное использование в равной степени облегчается свободными функциями и т. Д.
underscore_d

@Vlaz это правда, но дело в том, что в самолете .... ВСЕ должно бежать быстро.
Великая утка

0

Это не правило, это просто какой-то чувак, который отредактировал Википедию с парой цифр, взятых из воздуха, и назвал это правилом. Сравните с принципом Парето, который более твердо установлен в других контекстах. Я хотел бы посмотреть, какие исследования были сделаны (если таковые имеются) на точность этого "правила".

Но в основном ответ на ваш вопрос таков: некоторый код выполняется гораздо чаще, чем другой. Петли часто являются причиной этого. Другими причинами являются длительные вызовы, например, на внешние ресурсы, такие как веб-службы или носители данных.


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

Если вы предполагаете, что это широко используется в качестве практического правила, мне было бы интересно увидеть доказательства этого также! Или это просто еще одно мнение, извлеченное из воздуха, но подразумеваемое как фактическое?
Брэд Томас,

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

Ну, я не собираюсь покупать книгу, просто чтобы посмотреть исследование, на которое она, якобы, ссылается ... Можете ли вы опубликовать цитату из нее, которая показывает доказательства? Или вы на самом деле ничего не видели?
Брэд Томас

1
@BradThomas: Свидетельство против теории, что правило 90-10 было изобретено кем-то, кто редактировал Википедию, - то, что оно широко цитировалось, с номерами 90 и 10, за много лет до того, как Википедия существовала; Реальный принцип заключается не в том, что именно 10% кода составляет 90% времени выполнения, а в том, что в большинстве программ небольшая часть кода (10% или меньше) составляет такую ​​большую часть времени выполнения. -90% или более, что даже повышение производительности этой небольшой части кода на 10% приведет к сокращению общего времени выполнения более чем в 1000 раз по сравнению со всем остальным.
суперкат

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.