Сводная характеристика качества оптимизации штатных Си функций и функций ОС для работы с памятью
Качество оптимизации штатных функций, поставляемых вместе с компилятором, – весьма актуальный вопрос, поскольку от этого напрямую зависит производительность откомпилированной программы.
Вообще же, отношения к штатным функциям у программистов самые разнообразные: от полного нежелания использовать что-либо стандартное (стандартные вещи редко бывают хорошими), до безоговорочного их обожания (не надо думать, что разработчики компилятора глупее нас с вами).
Как же действительно обстоят дела на практике? Об этом можно узнать из таблицы ???3, приведенной ниже и описывающие ключевые особенности оптимизации базовых memory-функций популярных компиляторов и операционной системы Windows 2000. (Операционная система приведена лишь в качестве примера, т.к. использование функций семейства RtlxxxMemory, как было показано выше нецелесообразно – см. "Особое замечание по функциями Win32 API"):
memcpy/CopyMemory
|
|
|
| Microsoft Visual C++ 6.0
|
| Borland C++ 5.5
|
| WATCOM C++ 10
|
| Windows 2000
|
|
LIB
|
| intrinsic
|
|
копирование
|
| DWORD
|
| DWORD
|
| DWORD
|
| DWORD
|
| ––
|
|
выравнивание адресов источника и/или приемника
|
| выравнивает адрес приемника по границе 4 байт
|
| не выравнивает
|
| не выравнивает
|
| не выравнивает
|
| ––
|
|
memmove/MoveMemory
|
|
|
| Microsoft Visual C++ 6.0
|
| Borland C++ 5.5
|
| WATCOM C++ 10
|
| Windows 2000
|
|
LIB
|
| intrinsic
|
|
копирование не перекрывающихся блоков памяти
|
| DWORD, в прямом направлении
|
| –
|
| DWORD, в прямом направлении
|
| DWORD, в прямом направлении
|
| DWORD, в прямом направлении
|
|
копирование перекрывающихся блоков памяти пр
|
| src < dst
|
| DWORD, в обратном направлении
|
| –
|
| DWORD, в обратном направлении
|
| BYTE?, в обратном направлении
|
| DWORD, в обратном направлении
|
|
src > dst
|
| DWORD, в прямом направлении
|
| –
|
| DWORD, в прямом направлении
|
| DWORD, в прямом направлении
|
| DWORD, в прямом направлении
|
|
выравнивание адресов источника и/или приемника
|
| выравнивает адрес приемника по границе 4 байт
|
| –
|
| не выравнивает
|
| не выравнивает
|
| не выравнивает
|
|
<
В таблицах, приведенных ниже, содержится краткая характеристика качества оптимизации штатных Си-функций и функций операционной системы для работы со строками. Обратите внимание: ни операционная система, ни библиотеки распространенных компиляторов не являются полностью оптимальными и резерв для повышения быстродействия еще есть!
Поэтому, целесообразнее пользоваться вашими собственными реализациями строковых функций, вылизанных "по самые помидоры". Если этого не сделаете вы, никто не оптимизирует вашу программу за вас!
strlen/lstrlenA
|
|
|
| Microsoft Visual C++ 6.0
|
| Borland C++ 5.5
|
| WATCOM C++ 10
|
| Windows 2000
|
|
LIB
|
| intrinsic
|
|
определение длины
|
| align
|
| unalign
|
| BYTE, в прямом направлении
|
| DWORD, в прямом направлении
|
| BYTE, в прямом направлении
|
| BYTE, в прямом направлении
|
|
dword
|
| byte
|
|
выравнивание адресов источника и/или приемника
|
| не выравнивает
|
| не выравнивает
|
| выравнивает по границе 4 байт
|
| не выравнивает
|
| не выравнивает
|
|
степень разворота цикла (итераций)
|
| 1
|
| 1
|
| 1
|
| 1
|
| 1
|
|
strcpy/lstrcpyA
|
|
|
| Microsoft Visual C++ 6.0
|
| Borland C++ 5.5
|
| WATCOM C++ 10
|
| Windows 2000
|
|
LIB
|
| intrinsic
|
|
копирование
|
| определение длины источника
|
| не определяет
|
| BYTE
|
| BYTE
|
| BYTE
|
| BYTE
|
|
перенос строки
|
| align
|
| unalign
|
| DWORD
|
| DWORD
|
| DWORD
|
|
dword
|
| byte
|
|
выравнивание адресов источника и/или приемника
|
| не выравнивает
|
| не выравнивает
|
| не выравнивает
|
| не выравнивает
|
| не выравнивает
|
|
степень разворота цикла (итераций)
|
| 1
|
| 1
|
| 1
|
| 2
|
| 1
|
|
strcat/lstrcatA
|
|
|
| Microsoft Visual C++ 6.0
|
| Borland C++ 5.5
|
| WATCOM C++ 10
|
| Windows 2000
|
|
LIB
|
| intrinsic
|
|
копирование
|
| определение длины источника
|
| не определяет
|
| BYTE
|
| BYTE
|
| BYTE
|
| BYTE
|
|
определение длины приемника
|
| align
|
| unalign
|
| BYTE
|
| BYTE
|
| не определяет
|
| BYTE
|
|
dword
|
| byte
|
|
перенос строки
|
| align
|
| unalign
|
| DWORD
|
| DWORD
|
| BYTE
|
| DWORD, в прямом направлении
|
|
dword
|
| byte
|
|
выравнивание адресов источника и/или приемника
|
| не выравнивает
|
| не выравнивает
|
| не выравнивает
|
| не выравнивает
|
| не выравнивает
|
|
степень разворота цикла (итераций)
|
| 1
|
| 1
|
| 1
|
| 2
|
| 1
|
|
<
memset/FillMemory/ZeroMemory
|
|
Microsoft Visual C++ 6.0
|
Borland C++ 5.5
|
WATCOM C++ 10
|
Windows 2000
|
LIB
|
intrinsic
|
заполнение памяти
|
DWORD, в прямом направлении
|
DWORD, в прямом направлении
|
DWORD, в прямом направлении
|
DWORD, в прямом направлении
|
DWORD, в прямом направлении
|
выравнивание адреса приемника
|
выравнивает адрес приемника по границе 4 байт
|
не выравнивает
|
не выравнивает
|
не выравнивает
|
не выравнивает
|
memcmp/CompareMemory
|
|
Microsoft Visual C++ 6.0
|
Borland C++ 5.5
|
WATCOM C++ 10
|
Windows 2000
|
LIB
|
intrinsic
|
сравнение памяти
|
BYTE, в прямом направлении
|
BYTE, в прямом направлении
|
BYTE, в прямом направлении
|
BYTE, в прямом направлении
|
DWORD, в прямом направлении
|
выравнивание адресов источника и/или приемника
|
не выравнивает
|
не выравнивает
|
не выравнивает
|
не выравнивает
|
не выравнивает
|
Таблица 3 Сводная характеристика качества оптимизации штатных Си функций и функций ОС для работы с памятью
Что полезного можно почерпнуть из этой таблицы? Первое, что сразу бросается в глаза: крайне небрежная оптимизация штатных функций в компиляторах от Borland и WATCOM. Создается впечатление, что их разработчики вообще не ставили перед собой задачу достичь если не максимальной, то хотя бы приемлемой производительности.
Гораздо качественнее оптимизированы memory-функции штатной библиотеки компилятора Microsoft Visual C++, которые выгодно отличаются тем, что выравнивают адрес приемника на границу 4 байт, что в ряде случаев значительно увеличивает производительность (правда, как было показано в главе "Выравнивание данных" гораздо предпочтительнее выравнивать адрес источника, а не приемника). Тем не менее Microsoft Visual C++ не использует никаких прогрессивных алгоритмов оптимизации, описанных в главе "Оптимизация штатных Си-функций для работы с памятью", а функции memcmp он не оптимизирует вообще!
Словом, если вам нужна скорость – используйте собственные реализации функций для работы с памятью!
strcmp/lstrcmpA
|
|
Microsoft Visual C++ 6.0
|
Borland C++ 5.5
|
WATCOM C++ 10
|
Windows 2000
|
LIB
|
intrinsic
|
проверка
|
BYTE, в прямом направлении
|
BYTE
|
BYTE
|
DWORD, в прямом направлении
|
BYTE, в прямом направлении
|
выравнивание адресов источника и/или приемника
|
не выравнивает
|
не выравнивает
|
не выравнивает
|
не выравнивает
|
не выравнивает
|
степень разворота цикла (итераций)
|
2
|
2
|
2
|
8 (!)
|
1
|
strstr/---
|
|
Microsoft Visual C++ 6.0
|
Borland C++ 5.5
|
WATCOM C++ 10
|
Windows 2000
|
LIB
|
intrinsic
|
сравнение
|
BYTE, в прямом направлении
|
–
|
DWORD, в прямом направлении
|
BYTE, в прямом направлении
|
–
|
выравнивание адресов источника и/или приемника
|
не выравнивает
|
–
|
не выравнивает
|
не выравнивает
|
–
|
степень разворота цикла (итераций)
|
1
|
–
|
1
|
1
|
–
|
Таблица 4 Сводная таблица качества оптимизации штатных Си функций и функций ОС для работы со строками
Содержание раздела