Po pewnym czasie enter
stało się tak rzadko wykorzystywane, że Intelowi nawet nie chciało się optymalizować jego implementacji w swoich procesorach. Stąd taki enter
stał się znacznie wolniejszy od kombinacji push
+ mov
.
Postanowiłem sprawdzić, jak to jest z tą mityczną powolnością enter
:
[bits 32]
segment .text
global _enter_leave
_enter_leave:
enter 0, 0
nop
leave
ret
global _push_mov
_push_mov:
push ebp
mov ebp, esp
nop
mov esp, ebp
pop ebp
ret
global _enter_leave_20
_enter_leave_20:
enter 20, 0
nop
leave
ret
global _push_mov_20
_push_mov_20:
push ebp
mov ebp, esp
sub esp, 20
nop
mov esp, ebp
pop ebp
ret
#include <time.h>
#include <stdio.h>
extern void enter_leave();
extern void push_mov();
extern void enter_leave_20();
extern void push_mov_20();
int main()
{
const int count = 1000000000;
clock_t t0 = clock();
for (int i=0; i<count; i++)
enter_leave();
clock_t t1 = clock();
for (int i=0; i<count; i++)
push_mov();
clock_t t2 = clock();
printf("enter/leave\t%f s\n", (float)(t1-t0)/CLOCKS_PER_SEC);
printf("push/mov\t%f s\n\n", (float)(t2-t1)/CLOCKS_PER_SEC);
t0 = clock();
for (int i=0; i<count; i++)
enter_leave_20();
t1 = clock();
for (int i=0; i<count; i++)
push_mov_20();
t2 = clock();
printf("enter n/leave\t%f s\n", (float)(t1-t0)/CLOCKS_PER_SEC);
printf("push/mov/sub\t%f s\n", (float)(t2-t1)/CLOCKS_PER_SEC);
}
Atom N570 (1,66 GHz):
enter/leave 24.078000 s
push/mov 7.984000 s
enter n/leave 23.218000 s
push/mov/sub 7.985000 s
Core 2 Quad Q6600 (2,4 GHz)
enter/leave 5.031000 s
push/mov 4.547000 s
enter n/leave 5.031000 s
push/mov/sub 3.484000 s
Interesujące. Różnica bywa... różna. Ale to i tak w hello worldach bez znaczenia.