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