Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
книги хакеры / Питер_Гудлиф_Ремесло_программиста_Практика_написания_хорошего_кода.pdf
Скачиваний:
15
Добавлен:
19.04.2024
Размер:
9.23 Mб
Скачать

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

 

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

Какm

писать эффективный код

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

Как писать эффективный код

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

289Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

w

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

.c

 

 

.

 

 

 

 

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

Если лучше всего отказаться от оптимизации, то как достичь того, чтобы потребности в повышении эффективности кода вообще не воз% никало? Для этого нужно проектировать код с учетом его эффектив# ности и планировать надлежащее качество его работы с самого нача% ла, а не обстругивать его в последнюю минуту.

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

Как же примирить эти две, как может показаться, противоположные точки зрения? Без большого труда, потому что на самом деле они не противоречат одна другой. Есть две взаимодополняющие стратегии:

Писать эффективный код

Оптимизировать код потом

Если вы поставите себе задачу сразу писать ясный, хороший, эффек% тивный код, не потребуется впоследствии существенно его оптимизи% ровать. Есть мнение, что нельзя заранее знать, потребуется ли оптими% зация, поэтому нужно писать как можно проще, а оптимизацию про% водить только в том случае, если профилирование выявит узкие места.

Недостатки такого подхода очевидны. Если известно, что вам нужна структура данных с эффективными средствами поиска (поскольку программа должна быстро осуществлять поиск), следует выбрать би% нарное дерево, а не массив.1 Если такие требования перед вами не сто% ят, тогда выберите наиболее подходящее средство, которое решит за% дачу. Оно необязательно должно быть простейшим; обычный массив в C – это структура данных, которой трудно управлять.

Проектируя каждый модуль, не гонитесь бездумно за эффективностью – тратьте силы на оптимизацию, только если в этом есть необходимость. Уясните, какие требования предъявляются к производительности, и проверяйте на каждом этапе, удовлетворяют ли ваши решения этим требованиям. Если вы знаете, какой уровень производительности необ% ходим, проще проектировать код, удовлетворяющий требованиям эф% фективности. Кроме того, вы можете написать конкретные тесты, что% бы проверить, достигнут ли заданный уровень производительности.

1Однако, как всегда, не все так просто. Массивы могут обеспечивать луч% шую связность кэша, в то время как узлы бинарного дерева легко оказыва% ются раскиданными по всей памяти. Стоит рассмотреть такой вариант, как сортированный массив (время тратится при вставке элементов). Мерить,

мерить и еще раз мерить.

 

 

 

 

hang

e

 

 

 

 

 

 

C

 

E

 

 

 

X

 

 

 

 

 

-

 

 

 

 

 

d

 

F

 

 

 

 

 

 

t

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

to

 

 

 

 

w Click

 

 

 

290m

 

 

 

 

w

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

.

 

 

 

 

 

.c

 

 

p

 

 

 

 

g

 

 

 

 

df

 

 

n

e

 

 

 

 

-xcha

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

Глава 11. Жажда скоростиClick

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

w

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

.c

 

 

.

 

 

 

 

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

Пессимизации

Если не делать тщательных измерений, то ваши оптимизации лег% ко могут оказаться отнюдь не оптимальными. Оптимизация, иде% альная для одной ситуации, может резко снизить эффективность в другой. Приведем наглядный пример: оптимизация строк copy% on%write (копирование при записи).

В 1990 году данная оптимизация часто применялась к реализа% циям стандартных библиотек. Программы, интенсивно работав% шие со строками, тратили огромные ресурсы при копировании длинных строк – как в отношении загрузки процессора, так и расхода памяти. Копирование длинных строк требует дублиро% вания и перемещения большого объема данных. Автоматически генерируются многочисленные экземпляры строк, создаются временные объекты, которые вскоре выкидываются – в действи% тельности они никогда не модифицируются. Дорогостоящая операция копирования требует излишних расходов.

При оптимизации copy%on%write (COW) строковый тип данных преобразуется в некий умный указатель: действительные дан% ные строки хранятся в виде (скрытого) общего представления. В итоге копирование строки сводится к простому копированию умного указателя (прикреплению нового умного указателя к об% щему представлению) вместо дублирования всего содержимого строки. Только в случае модификации строки осуществляется копирование ее внутреннего представления, а также изменение умного указателя. Такая оптимизация позволяет избежать вы% полнения многочисленных операций копирования.

COW хорошо работала в однопоточных программах; она заметно увеличивала скорость работы. Однако при использовании COW% строк в многопоточных программах возникли проблемы. (На са% мом деле, проблема появляется даже в однопоточных програм% мах, если класс строк COW собран с поддержкой многопоточно% сти.) Реализация требует очень консервативной блокировки по% токов во время операций копирования, и эти блокировки стано% вятся существенно узким местом. Внезапно программа, которая раньше летала, начинает ползти. Оптимизация COW оказалась существенной пессимизацией.

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

 

 

 

 

hang

e

 

 

 

 

 

 

C

 

E

 

 

 

X

 

 

 

 

 

-

 

 

 

 

 

d

 

F

 

 

 

 

 

 

t

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

to

 

 

 

 

w Click

 

 

 

Резюмеm

 

 

 

 

w

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

.

 

 

 

 

 

.c

 

 

p

 

 

 

 

g

 

 

 

 

df

 

 

n

e

 

 

 

 

-xcha

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

291Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

w

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

.c

 

 

.

 

 

 

 

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

Вот некоторые простые конструктивные решения, которые увеличи% вают производительность и облегчают последующую оптимизацию:

Минимизируйте применение функций, которые реализованы на удаленных машинах либо требуют обращения к сети или медлен% ной системе хранения данных.

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

Пишите модульный код, чтобы можно было оптимизировать от% дельные блоки, не переписывая заново остальные.

Резюме

Прогресс технологии одаряет нас все более совершенными средствами для движения вспять.

Олдос Хаксли

Высокая эффективность кода не столь важна, как некоторым кажет% ся. Хотя иногда приходится засучить рукава и поковыряться в коде, в целом нужно активно избегать проведения оптимизации. Поэтому до начала работы над программным продуктом выясните, какие требова% ния предъявляются к его производительности. На каждом этапе раз% работки проверяйте, обеспечивается ли требуемое качество. Тогда оп% тимизация вам не понадобится.

Если вы все же проводите оптимизацию, делайте это в высшей мере методично и осторожно. Поставьте себе четкую цель и после каждого шага проверяйте, приблизились ли вы к ней. Опирайтесь на твердые данные, а не на свои догадки. Разрабатывая код, заботьтесь об эффек% тивности своих решений, но не в ущерб качеству кода. Оптимизация на уровне кода оправдана только в случае особой необходимости.

Хорошие программисты…

Прибегают к оптимизации толь% ко в случае крайней необходи% мости

Проводят оптимизацию мето% дически, подходя к ней взве% шенно и осторожно

Рассматривают альтернатив% ные решения и возможности конструктивных усовершенст% вований, прежде чем решиться на оптимизацию на уровне кода

Стремятся к тому, чтобы опти% мизация не ухудшила качество кода

Плохие программисты…

Начинают оптимизировать, не удостоверившись, что код недос% таточно эффективен

Бездумно набрасываются на код, который кажется им узким ме% стом, не выполнив предвари% тельных замеров и исследований

Не задумываются над общей картиной: каковы будут послед% ствия их оптимизации для ос% тальных участков кода и моде% лей работы

Считают, что скорость важнее качества кода