Что? Где? Когда?
Что оптимизировать?
Программисты тратят огромное количество времени, размышляя и беспокоясь о некритичных местах кода, и пытаются оптимизировать их, что исключительно негативно сказывается на последующей отладке и поддержке. Мы должны вообще забыть об оптимизации в, скажем, 97% случаев; более того, поспешная оптимизация является корнем всех зол. И напротив, мы должны уделить все внимание оставшимся 3%.Дональд Кнут, Структурное программирование с операторами go to
Самая сложная часть оптимизации — это не процесс оптимизации кода, а непосредственно принятие решения: делать ее или нет. Для этого существует всего несколько четких правил, все остальное — советы и рекомендации.
Отчасти проблема заключается в том, что оптимизацию сложно выполнить действительно хорошо. Очень просто скатиться в бессмысленные ритуалы и повторение чьих-то действий. С другой стороны, нередко встречаются также приятные неожиданности в местах, где их не совсем ищешь. Вот почему советы экспертов о производительности, как правило, имеют афористично-противоречивый вкус:
Если вы не знаете, что вы делаете, не делайте этого! Вы поймете, когда будете знать, что делать.
Ах, да, и не забывайте о производительности при проектировании программы.
То есть, эксперты боятся поощрять глупости, но не могут позволить себе игнорировать возможные выгоды.
Где и как оптимизировать?
Популярная цитата Кнута о преждевременной оптимизации нужна не для того, чтоб при случае «бить» ею программистов, как кнутом. Это остроумное замечание было высказано в процессе разговора о рычагах, в который едва заметно, но справедливо был встроен отрывок об использовании операторов go to для написания быстрого и читабельного кода. Интересно, что целью этого труда была попытка предостеречь от слишком серьезного восприятия знаменитых слов Эдсгера Дейкстры о вреде go to. И очень хорошо, что мы вообще можем об этом говорить.
Структурное программирование с операторами go to включает в себя два важных, хорошо себя зарекомендовавших способа увеличить производительность.
Оптимизация без проведения замеров и снятия метрик — не более чем глупость.
Как и попытка оптимизировать сразу все и вся.
Самые значительные успехи в производительности, как правило, являются результатом оптимизации незначительных участков кода, «те самые необходимые 3%» от всего объема, которые определяются путем тщательных замеров скорости работы кода.
Хорошо измерив производительность кода, вы сможете увидеть, когда и в каком месте оптимизация, скорее всего, даст нужный эффект. Тем не менее, это не значит, что ее тут же стоит применять. Кнут, в конечном счете, перекладывает ответственность за решение на гипотетического «хорошего» и «мудрого» программиста, который в состоянии сам принять решение. Отлично, но как?
Затрудняюсь ответить. Повышение производительности есть, или, скорее, должно быть процессом взвешивания всех за и против. Это, как если бы вы решали, сколько усилий потратить на тестирование или безопасность. Переборщить можно со всем: слишком много тестирования, слишком много рефакторинга кода или чего-либо еще хорошего.
Когда оптимизировать?
В отличие от тестирования или отладки, работа над производительностью может быть отложена либо впритык к дате релиза, либо даже на период после него. Мой опыт показывает, что отладка имеет наибольший смысл на продуманных системах с уже отлаженной архитектурой. Только что написанный код практически всегда, можно сказать, по определению, оказывается медленным, но вполне вероятно, что он будет заменен во время бета тестирования. Если вам не собираются дополнительно платить за то, что, скорей всего, все равно будет переписано, а также за потенциально утраченное время на реально важные вещи, то – пустая трата времени.
Также, оптимизация имеет смысл, когда без нее невозможно завершить программу и отправить ее в релиз. Увеличение производительности очень важно, когда ваша система располагает ограниченными ресурсами или вам трудно менять программное обеспечение постфактум. Этот подход распространен в программировании игр. Кроме того, наблюдается тенденция возвращения его в жизнь программиста в связи с расширением сектора программирования под мобильные устройства.
Но даже если учитывать все эти нюансы, все равно нет никаких гарантий успеха. В начале 2000-х я помогал разрабатывать систему для рекламы в поисковиках. У нас не было денег, поэтому мы постоянно работали над тем, чтоб увеличить производительность. Бывший технический директор наших конкурентов, глядя на нашу работу, вынужден был признать, что мы выжали из нашего «железа» в десять раз больше его обычных показателей. Но, к сожалению, мы потратили на производительность так много времени, что совсем не уделили внимание безопасности. Убытки от мошенников и постоянные возвраты оплаты очень быстро сделали нашу компанию банкротом. С одной стороны, мы сделали потрясающий с инженерной точки зрения продукт. С другой – мы работали совсем не над тем.
Эти пыльные предупреждающие знаки на тернистой дороге оптимизации находятся там не просто так. Они могут обескураживать, так как смысл их в том, что «вы вероятно еще не достаточно опытны для того, чтобы использовать нужные инструменты правильно». Что ж, если это вас не испугало, предлагаю двигаться дальше. Впереди еще много «подводных камней».