Burster_TIL писал(а):Не совсем так. Я говорил про то, что я компилирую две ф-ции в одном проекте. Она ниже. И у неё ощутимо большее число тиков выходит. Твоя и эта компилируется при одинаковых условиях. Ибо это всё в одном проекте.
Давай для начала договоримся о таких вещах, чтобы все кто читает этот форум понимали лучше.
1) Когда ты говоришь в "одном проекте" то ты сразу прилагай
весь текст программы, желательно аттачем (положенным в .zip). Отлаживать куски кода очень и очень неблагодарное дело.
2) нету "твоей" и "этой" функции. Т.к. яваскрипт ещё не полностью захавал мозг делфи программистам, мы всё ещё присваиваем имена процедурам и функциями. И по-этому используй выражения вроде. "Я говорил про то, что я компилирую две ф-ции в одном проекте. Она -Test_Speed - ниже. И у неё ощутимо большее число тиков выходит. Твоя (BigTest) и эта (Test_Speed) компилируется при одинаковых условиях"
3) пожалуйста используй
тэг code (статья на английском но с картинками понятно!)
Это важно, т.к. если ты и я может кое-как и понимаем где чья функия, другие участники не поймут.
Ну а теперь о разнице! Как я говорил выше, если ты скомпилируешь програмку с ключиком "-al" то у тебя появится ассебмлерный код.
Но лучше сделать даже так:
- Код: Выделить всё
fpc -al -O3 -Amasm test.pas
Разница будет в синтаксисе ассебмлера. Если использовать -Amasm то ассебмлер будет в
Интеловском-синтаксе, который может увидеть и в Delphi. Очень удобно для сравнения скажем Delphi и FPC кода.
Так вот, смотрим в ассемблеры. Цикл для Test_Speed выглядит следующий образом
- Код: Выделить всё
; [35] for j:=0 to 19 do
mov dword ptr [ebp-20],0
dec dword ptr [ebp-20]
ALIGN 4
@@j34:
inc dword ptr [ebp-20]
; [37] i:=1000;
mov dword ptr [ebp-4],1000
; [38] T1:=Get__RDTSC;
call P$PROGRAM_GET__RDTSC$$INT64
mov dword ptr [ebp-16],eax
mov dword ptr [ebp-12],edx
; [39] for i:=0 to 1000 do
mov dword ptr [ebp-4],0
dec dword ptr [ebp-4]
ALIGN 4
@@j41:
inc dword ptr [ebp-4]
; [41] a:=0;
mov ebx,0
cmp dword ptr [ebp-4],1000
jl @@j41
; [43] T2:=Get__RDTSC;
call P$PROGRAM_GET__RDTSC$$INT64
mov dword ptr [ebp-8],eax
mov esi,edx
а цикл для BigTest выглядит так:
- Код: Выделить всё
; [21] T1:=Get__RDTSC;
call P$PROGRAM_GET__RDTSC$$INT64
mov ebx,eax
mov esi,edx
; [22] i:=1000;
mov eax,1000
; [23] for i:=0 to 1000 do
mov edx,0
dec edx
ALIGN 4
@@j23:
inc edx
; [25] a:=0;
mov eax,0
cmp edx,1000
jl @@j23
; [26] T2:=Get__RDTSC;
call P$PROGRAM_GET__RDTSC$$INT64
Так вот, обрати внимание что в коде Test_Speed можно часто увидеть выражение вроде:
- Код: Выделить всё
dword ptr [ebp-NNN]
а в коде BigTest их нет вообще. И это причина тормозов - dword ptr [ebp-NNN] - заставляет процессор оперировать с памятью.
Тогда как BigTest оперирует не с памятью а исключительно с регистрами процессора.
Почему FPC так сделал. Обычно счётчики цикла лежат в регистре, а не памяти процессора, но т.к. у тебя есть вложенный цикл, то регистров (коих мало) на всё не хватит, и FPC генерирует код, который оперирует с памятью. Что вызывает "тормоза" но зато код работает.
В реальной жизни, когда цикл будет делать нечто большее, чем просто присваивать 0 в переменную a, оперирования с памятью не избежать вообще, и скорость сравняется и между циклами и между компиляторами (delphi и fpc).