Книга знаний |
|
Инф. технологии |
|
В статье предпринята попытка проанализировать, ведет ли объектный стиль программирования к существенному замедлению кода по сравнению с процедурным стилем. | Автор статьи: romix | Редакторы: Последняя редакция №13 от 08.02.07 | История URL: http://kb.mista.ru/article.php?id=472 |
Для проверки, в какой же именно код транслирует Delphi тот или иной пример, я использовал отладчик SoftICE. Чтобы остановить выполнение на нужном фрагменте кода, я даю SoftICE команду
BPX MessageBoxA(ставлю точку останова на функции MessageBox). Чтобы дать эту команду, я открываю окно отладчика нажатием Ctrl-D, ввожу эту команду и нажимаю Enter.
И, соответственно, вставляю в свой код на Delphi вызов MessageBox (эта системная функция Windows выводит окно предупреждения). Когда срабатывает "бряк" (breakpoint), я выхожу "наверх" из функции нажатием клавиши F12, после чего пошагово исполняю код нажатием клавиш F8 (пошаговое выполнение) или F10 (то же самое, без захода в процедуры). В приведенных ниже примерах кода вызов MessageBox, который я использую только для этой цели (чтобы остановить выполнение в SoftICE), помечен синим цветом.
В этом примере я просто вывожу сообщение (MessageBox) из метода объекта и из процедуры соответственно. Сгенерированный транслятором машинный код почти не отличается, за исключением передачи в регистре eax ссылки (указателя) на объект в случае с применением ООП.
В объектном стиле | В процедурном стиле |
---|---|
program ObjTest; uses Windows; type T_TEST = Class procedure test(); end; procedure T_TEST.test(); begin MessageBox(0, 'test', 'test',0); end; var obj: T_TEST; begin obj:=T_TEST.Create; obj.Test(); obj.Test(); obj.Free; end. |
program ObjTest; uses Windows; procedure test(); begin MessageBox(0, 'test', 'test',0); end; begin Test(); Test(); end. |
mov eax, ebx call 00403620 mov eax, ebx call 00403620 ... 00403620: push 00 push 00403640; "test" push 00403640; "test" push 00 call User32!MessageBoxA ret |
call 00401E90 call 00401E90 ... 00401E90: push 00 push 00403640; "test" push 00403640; "test" push 00 call User32!MessageBoxA ret |
В объектном стиле | В процедурном стиле |
---|---|
program ObjTest; uses Windows; type T_TEST = Class function add(a,b: Integer):Integer; end; function T_TEST.add(a,b: Integer):Integer; begin MessageBox(0, 'test', 'test',0); Result:=a+b; end; var obj: T_TEST; begin obj:=T_TEST.Create; obj.add(2,3); obj.add(3,4); obj.Free; end. |
program ObjTest; uses Windows; function add(a,b: Integer):Integer; begin MessageBox(0, 'test', 'test',0); Result:=a+b; end; begin add(2,3); add(3,4); end. |
mov ecx, 00000004 mov edx, 00000003 mov eax, ebx call 00403620 ... 00403620: push ebx push esi mov esi, ecx mov ebx, edx push 00 push 00403640; "test" push 00403640; "test" push 00 call User32!MessageBoxA lea eax, [ebx+esi] pop esi pop ebx ret |
mov edx, 00000004 mov eax, 00000003 call 00401E90 ... 00401E90: push ebx push esi mov esi, edx mov ebx, eax push 00 push 00403640; "test" push 00403640; "test" push 00 call User32!MessageBoxA lea eax, [ebx+esi] pop esi pop ebx ret |
Переделаем этот же пример так, чтобы числа, которые нужно сложить, передавались не через параметры функции, а через поля класса.
В объектном стиле | В процедурном стиле |
---|---|
program ObjTest; uses Windows; type T_TEST = Class a: Integer; b: Integer; function add():Integer; end; function T_TEST.add():Integer; begin MessageBox(0, 'test', 'test',0); Result:=a+b; end; var obj: T_TEST; begin obj:=T_TEST.Create; obj.a:=2; obj.b:=3; obj.add(); obj.a:=3; obj.b:=4; obj.add(); obj.Free; end. |
program ObjTest; uses Windows; var a: Integer; b: Integer; function add():Integer; begin MessageBox(0, 'test', 'test',0); Result:=a+b; end; begin a:=2; b:=3; add(); a:=3; b:=4; add(); end. |
mov dword ptr[ebx+04], 0000003 mov dword ptr[ebx+08], 0000004 mov eax, ebx call 00403620 ... 00403620: push ebx mov ebx, eax push 00 push 00403640; "test" push 00403640; "test" push 00 call User32!MessageBoxA mov eax, [ebx+04] add eax, [ebx+08] pop ebx ret |
mov dword ptr[004036EC], 0000003 mov dword ptr[004036F0], 0000004 call 00401E90 ... 00401E90: push 00 push 00403640; "test" push 00403640; "test" push 00 call User32!MessageBoxA mov eax, [004036EC] add eax, [004036F0] ret |
Как видим в вышеприведенных примерах, различия малосущественны, и оправданы необходимостью передавать дополнительную переменную - ссылку на объект.
Описание
| Рубрикатор
| Поиск
| ТелепатБот
| Захваченные статьи
| Установки
| Форум
|