К. Касперски - Техника оптимизации программ, Эффективное использование памяти (1127752), страница 43
Текст из файла (страница 43)
Чтобы убедиться в этом, достаточно вызвать любую из функций напрямую в обход БОК. НтнзтАИСК Ьс №ппбег КГ1иоееиепогу ссо1б ( егбса11 *КЬ1иоееиеиогу)(ооьб бег, ссоьд* *го, апГ соопг)с Л=ЬоабЬкьгагу("КККИКЬ32,ОЬЬ")) А11могемеиогу = (го1б ( агбса11 *)(го№б *бег, еоьб* агс, гпг сопке)) ОеЬРгоскддгееа(Ь, "АГ1Могеиеиогу")( Одна из возможных реализаций приведена далее (листинг 2.37, обработка ошибок по соображениям наглядности не приведена). Глава а ВПРОЧЕМ, ИСПОЛЬЗОВатЬ фуНКцИЮ КП1Мопеиепопу ВМЕСТО пепе опе — НЕ ОЧЕНЬ хорошая идея, и М!сгозой не зря заблокировала ее вызов. Функция кетм м у совершенно отвратительно оптимизирована. Во-первых, она не выравнивает адреса перемещаемых блоков памяти, а, во-вторых, перекрывающиеся блоки памяти в случае о < сап копирует по байтам, что нельзя признать оптимальным.
На платформе Р-П1/733/!33/!00/1815ЕР функция кп1мопемепопу проигрывает штатной функции певипопе компилятора М!сгозой 'у'!зла! С++ 6.0 чуть ли не в полтора раза! Правда, на АМ!3 Абт!оп !050/!00/!00/у1А КТ133 ситуация дИаМЕтраЛЬНО ПрОтИВОПОЛОжНая — ЗДЕСЬ фуНКЦИЯ пепопе ОТСТДЕТ ОТ Саосй конкурентки, причем весьма значительно — на целых 30%! С функцией у111мепопу ситуация более постоянна.
На всех системах она показывает ничуть не худший результат, чем штатная функция языка пепаеп и потому совершенно все равно, какую из них использовать. Аналогичная картина наблюдается и с функцией з ом у, являющейся прямой родственницей гх11мепопу, но заполняющей блок памяти нулями, а не произвольным значением. С другой стороны, с практической точки зрения функция Г111мепопу На ЦЕЛЫХ ЧЕТЫРЕ СИМВОЛа ДЛИННЫ, ЧЕМ пепаее И ПОТОМУ ИСПОЛЬЗО- ванне последней все же предпочтительнее. Впрочем, эта оценка достаточна субъективна. Встречаются эстеты, которые находят, что функция г щм у выглядит красивее, чем пепаеп и к тому же намного легче читается. Что ж, выбирайте то, что вам больше по душе! Может показаться, что при инициализации множества крошечных блоков памяти использование функции г 11м у повлечет за собой значительные НаКЛаДНЫЕ РаСХОДЫ На МНОГОКРатНЫй ВЫЗОВ ФУНКЦИИ (пе еп В ОТЛИЧИЕ От нее может быть непосредственно "вживлена" в исполняемый код как 1к11ке, — обычно она и "вживляется").
На самом же деле современные процессоры так быстры, что временем вызова функции можно полностью пренебречь. Разница в производительности функций и . аеп и г 11м у едва ли превысит несколько процентов, что практически не скажется на общем быстродействии программы. Вы, наверное, уже обратили внимание, что в списке Ъу!Н32 АР1-функций отсутствует какой бы то ни было аналог функции пепопр. Это действительно странно, поскольку в файле ЪУ1!Ч!ЧТ.Н такая функция все-таки есть: ()Оесгпе кезляоаз)аппп)пу (Сеаеппаеаоп, Яоппое, Ьепепь) ()пепопр ( (Оеае1пае1оо), (Яоопое), (1.епдеш ) ) А среди функций, экспортируемых !ЧТ13Ь1..Р1.1., есть функция КП1С р М опу, КОтОрая, КаК НЕтрудНО доГадатьея ИЗ ЕЕ НазВаНия, ИМеННО та, КОтсрая НаМ И НужНа! ПРИЧЕМ, В ОТЛИЧИЕ От фуНКцИИ К11иопеМепопу, Эта 215 Оперативная память функция сравнения памяти достаточно прилично оптимизирована и даже обгоняет штатную функцию и и р компилятора М!сгозой Ч!зца! С++ 6.0 (рис. 2.48).
На Р-Н1/733/133/1815ЕР разрыв в производительности составляет 40%, а на АМВ Аг)т!Оп 1050/100/100/Ч!А КТ133 — 15%. Рис. 2.48. Сравнительная характеристика штатных функций компилятора м!сговогт ьчвцв! с+ь и эквивалентных им функций операционной системы. Кстати, все они в той или иной степени неоптимальны К сожалению, функция вттссирагеиеисту не реализована на %!пг)отуз 9х и программа, ее использующая, будет работать только под тЧ!пг!Отуз 1к!Т/ 'ту'!пг!Отуз 2000. Конечно, можно распространять свой продукт вместе с библиотекой )х!Т13ЬЬ.РЬЬ, позаимствованной из каталога тЧ1)х!1нТ~ЯУБТЕМ (только переименуйте ее во что-нибудь другое, т. к. в 5Ч!пг!Оутз 9х уже есть своя библиотека ХТОЬЬ.13ЬЬ), но не проще ли самостоятельно реализовать фуНКЦИЮ иеесггр, ТЕМ боЛЕЕ ЧТО В ЭТОМ НЕТ НИЧЕГО СЛОЖНОГО7 ИЗЮМИНКа функции встсоирьтемеисту заключается в том, что в отличие от функции р она сравнивает память не байтами, а двойными словами.
Вот и весь секрет ее производительности! Заключительный вердикт: при разработке критичных к быстродействию прилоисений лучше всего использовать собственные реализации грункций, работаютцих с памятью, оптимизированных с учетом рекомендаций, приводимых в данной главе. И штатные функции языка, и функции операционной системы в той или иной степени неоптимальны. Глава 2 Сводная характеристика качества оптимизации штатных С-функций и функций ОС для работы с памятью Таблица 2.3.
Сводная характеристика качества оптимизации штатных С-функций н функций ОС для работы с памятью М1сгоеон тпвиаг С++ 0.0 Вог1апв С++ 6.0 чтдтсОм С++ 10 ЧЧ1пбовгв 2000 Операция 1.1В 1птипв!с тетсру/соруме тогу ОЧЧОВО ОЧЧОВО ОЧЧОВО ОЧЧОВО Копирование Выравнивание ад- ресов источника и/ипи приемника выравнивает не выравни- адрес прием- вает ника по границе 4 байт не выравни- вает не выравни- вает итоге/ноееме те тогу ОЧЧОВО, в прямом на правлении ОЧЧОВО, в прямом направле- нии ОЧЧОВО, в прямом на- правлении ОЧЧОВО, в прямом на правлении Копирование не- перекрывающихся блоков памяти ОЧЧОВО, в ВУТЕ, в обобратном ратном нанаправлении правлении ОЧЧОВО, в обратном направле- нии ОЧЧОВО, в обратном на- правлении Копирование перекрывающихся блоков памяти и тг у о и Качество оптимизации штатных функций, поставляемых вместе с компилятором, — весьма актуальный вопрос, поскольку от этого напрямую зависит производительность откомпилированной программы.
Вообще же, отношения к штатным функциям у программистов самые разнообразные: от полного нежелания использовать что-либо стандартное (стандартные вещи редко бывают хорошими) до безоговорочного их обожания (не надо думать, что разработчики компилятора глупее нас с вами). Как же действительно обстоят дела на практике? Об этом можно узнать из табл. 2лч приведенной далее и описывающей ключевые особешюсти оптимизации базовых тпешогу-функций популярных компиляторов и операционной системы ЧЧ!пг)отчз 2000. (Операционная система приведена лишь в качестве примера, т.
к. использование функций семейства ягтх и у, как было показано выше, нецелесообразно — см. равд. "Особое замечание ло функциям Ил32АРР'этой главы). Оперативная память г1/ 7абпица 2. 3 !окончание) М1сгоеои Рлвов1 С++ 6.0 тЧ1пооиа 2000 Вог1апо с++ Б.в ЧЧАТСОМ С++ 10 Операция ЫВ 1птг1пв1с аепаюее/ветен еаогу ОЧЧОВО, в прямом на- правлении ОЧЧОЯО, в прямом на- правлении ОЧЧОВО, в прямом на- правлении ОЧЧОЯО, в прямом направле- нии не выравни- вает не выравни- не выраввает нивает выравнивает адрес прием- ника по грани- це 4 байт ггттнеаогу/г ееаеег/ егонегеогу ОЧЧОВО, в прямом на- правлении ОЧЧОВО, в прямом направле- нии ОЧЧОВО, в прямом на- правлении ОЧЧОВО, в прямом на- правлении ОУЧОВО, в прямом на- правлении Заполнение памяти Выравнивание ад- реса приемника не выравни- вает не выравни- не выраввает нивает не выравни- вает выравнивает адрес прием- ника по грани- це 4 байт егер/соареген епюгу ВУТЕ, в прямом на- правлении ОЧЧОВО, в прямом направле- нии ВУТЕ, в прямом на- правлении ВУТЕ, в прямом на- правлении Сравнение памяти ВУТЕ, в пря мом направ ленин Выравнивание ад- ресов источника и/или приемника не выравни- не выравни- не выраввает вает нивает не выравнива- ет не выравни- вает Что полезного можно почерпнуть из этой таблицы? Первое, что сразу бросается в глаза: крайне небрежная оптимизация штатных функций в компиляторах от Вог1апб и те/АТСОМ.
Создается впечатление, что их разработчики вообше не ставили перед собой задачу достичь если не максимальной, то хотя бы приемлемой производительности. Гораздо качественнее оптимизированы птешогу-функции штатной библиотеки компилятора М1сгозоГг Ч1зпа1 С++, которые выгодно отличаются тем, что выравнивают адрес приемника на границу 4 байт, что в ряде случаев значительно увеличивает производительность (правда, как было показано в г?В Глава 2 равд. "Выравнивание данных" этой главы, гораздо предпочтительнее выравнивать адрес источника, а не приемника).
Тем не менее, М!сгозой Юнца! С++ не использует никаких прогрессивных алгоритмов оптимизации, описанных в разд. "Оптимизация штатных С-функций для работы с памятыю" этой главы, а функции г .р он не оптимизирует вообще! Словом, если вам нужна скорость — используйте собственные реализации функций для работы с памятью! Оптимизация строковых штатных С-функций С разительным отличием скорости обработки двойных слов и байтов мы уже столкнулись (см. разд.