Медленный компилятор FPC
Модератор: Модераторы
-
Burster_TIL
- новенький
- Сообщения: 46
- Зарегистрирован: 25.09.2013 02:05:28
Медленный компилятор FPC
Написал простой цикл в котором вызывается простая функция и оба проекта реализовал как на FPC 2.6.4, так и на Delphi-7. В итоге обнаружил, что время выполнения отличается в разы. Delphi-7 оказался ощутимо быстрее. Время замерял и там и там функцией RDTSC. То есть в тиках процессора. В теле цикла вообще убрал вызов функции и оставил только сам цикл. Всё равно работает медленней раз в 7 чем Delphi. Не очень понятно, почему такие тормоза. Я понимаю, что хотя бы был медленней такой простой тест задаче на какие-то проценты, но в разы - это вообще капец какой-то.
-
alex208210
- постоялец
- Сообщения: 207
- Зарегистрирован: 12.05.2010 13:16:51
о какова разница работы цикла delphi и fpc в linux ?
-
Burster_TIL
- новенький
- Сообщения: 46
- Зарегистрирован: 25.09.2013 02:05:28
alex208210 писал(а):о какова разница работы цикла delphi и fpc в linux ?
А при чём тут Linux? Всё проверялось на одной машине и в одной ОС. WinXP/32 SP3. Проверка дала, что в простом цикле как пустом так и с вызовом ф-ции, PFC тормозит конкретно. Увеличил даже размер цикла чтобы промежуточные результаты визуально можно было видеть на экране по мере их появления. Даже без засекания через RTDSC видно что вывод ощутимо медленней в FPС. Совершенно не ожидал такого.
Burster_TIL писал(а):Время замерял и там и там функцией RDTSC. То есть в тиках процессора.
если замеры ведутся функцией RDTSC то нужно сразу же показывать листинг assembler-а из Delphi и FPC, без лишних вопросов.
Это все хорошо, но не понятно замер был работающей программы в режиме отладки или нет?
Ошибка в коде. В зависимости от теста можно получить разные результаты. И методика тестирования тоже опишите. Она тоже влияет.
Но в целом меня оптимизация FPC не порадовала.
Но в целом меня оптимизация FPC не порадовала.
- *Rik*
- постоялец
- Сообщения: 453
- Зарегистрирован: 19.04.2011 12:18:51
- Откуда: Урал
- Контактная информация:
Да пофиг. Вы на FPC драйвера что-ли писать собрались? Для меня есть понятие приемлемое быстродействие, в этом плане FPC для моих задач более чем. Для меня главное переносимость между платформами, в т.ч. приложений с GUI, а вопрос чего там быстрее вообще на последнем месте. FPC и Lazarus прошли долгий и сложный путь, у разработчиков нет таких ресурсов как у Эмбаркадеро, взамен мы можем использовать его абсолютно бесплатно и на сегодняшний день, компилятор FPC и Lazarus накопили достаточный вес, что-бы например я, ушел на них с лицензионного Delphi, а всякая ерунда типа размер исполняемых файлов больше, быстродействие дельфийскому ПО уступает - это незначительные мелочи, которые меркнут по сравнению с "Написав один раз, собирай везде".
-
Burster_TIL
- новенький
- Сообщения: 46
- Зарегистрирован: 25.09.2013 02:05:28
скалогрыз писал(а):если замеры ведутся функцией RDTSC то нужно сразу же показывать листинг assembler-а из Delphi и FPC, без лишних вопросов.
Да без проблем. Ассемблерная процедура RDTSC вызывается всего 2 раза и из всего вычислительного процесса почти ничего сжирать не должна.
FUNCTION Get__RDTSC:Int64;ASSEMBLER;REGISTER; //Это извлечение тиков в FPC
Asm
RDTSC
End;
FUNCTION RDTSC_Int64:Int64; //Тоже самое в Delphi
Begin
Asm
db $0F; db $31;
{$IFDEF Cpu386}
mov [RDTSC_TimeStamp.Lo], eax
mov [RDTSC_TimeStamp.Hi], edx
{$ELSE}
db D32
mov word ptr RDTSC_TimeStamp.Lo, AX
db D32
mov word ptr RDTSC_TimeStamp.Hi, DX
{$ENDIF}
End;
Result:=RDTSC_TimeStamp.Whole;
End;
FUNCTION HexToSymbol(b:Byte):Byte; //Простая процедура
Begin
if b<58 then HexToSymbol:=b-48;
if b>64 then HexToSymbol:=b-55;
End;
Вызываем такой незатейливый код
T1:=RDTSC_Int64;
for i:=0 to 1000 do
Begin
B:=HEXToSymbol(100);
End;
T2:=RDTSC_Int64;
И выводим разницу Т2-Т1
В случае Delphi мы имеем 10586 тиков
В случае FPC имеем 28894 тика в первом вызове.
В других если не выходить из программы меньше. Порядка 18000
если же убрать фц-ию HexToSymbol и оставить просто цикл, то Delphi даёт 1965 а FPC 6753.
Как-то уж совсем тухло.
Добавлено спустя 3 минуты 56 секунд:
*Rik* писал(а):Да пофиг. Вы на FPC драйвера что-ли писать собрались? Для меня есть понятие приемлемое быстродействие, в этом плане FPC для моих задач более чем. Для меня главное переносимость между платформами, в т.ч. приложений с GUI, а вопрос чего там быстрее вообще на последнем месте. FPC и Lazarus прошли долгий и сложный путь, у разработчиков нет таких ресурсов как у Эмбаркадеро, взамен мы можем использовать его абсолютно бесплатно и на сегодняшний день, компилятор FPC и Lazarus накопили достаточный вес, что-бы например я, ушел на них с лицензионного Delphi, а всякая ерунда типа размер исполняемых файлов больше, быстродействие дельфийскому ПО уступает - это незначительные мелочи, которые меркнут по сравнению с "Написав один раз, собирай везде".
Какие нафиг драйвера? Например рекурсивный двумерный фильтр для изображения. Он должен на лету это делать для камеры. И на него нужно тратить как можно меньше времени. Это как пример. Или например медианный фильтр некой ф-ции, данные которого непрерывно идут с АЦП. Ну и т.д. Переносимость для меня вообще никакой роли не играет. Играет прежде всего быстродействие. С Delphi & Embarcadero я не уходил. Их платность не пугает ибо в сети полно взломанных версий. Я привёл простой цикловый пример. Какие уж нужны такие невероятные ресурсы по сравнению с Emabrcadero чтобы в этом примере так не уступать их компиляторам?
Добавлено спустя 1 минуту 3 секунды:
Pavia писал(а):шибка в коде. В зависимости от теста можно получить разные результаты. И методика тестирования тоже опишите. Она тоже влияет.
Да какая уж ошибка в коде, когда пример тривиальнейший?!
Добавлено спустя 1 минуту 5 секунд:
Sharfik писал(а):Это все хорошо, но не понятно замер был работающей программы в режиме отладки или нет?
Запускал программу и не из среды. Тот же результат.
Burster_TIL писал(а):скалогрыз писал(а):если замеры ведутся функцией RDTSC то нужно сразу же показывать листинг assembler-а из Delphi и FPC, без лишних вопросов.
Да без проблем. Ассемблерная процедура RDTSC вызывается всего 2 раза и из всего вычислительного процесса почти ничего сжирать не должна.
да не процедуры листинг (т.к. одинакова будет для обоих компиляторов) ,а циклов
включая реализации HEXToSymbol
Burster_TIL писал(а):FUNCTION RDTSC_Int64:Int64; //Тоже самое в DelphiBegin Asm db $0F; db $31; {$IFDEF Cpu386} mov [RDTSC_TimeStamp.Lo], eax mov [RDTSC_TimeStamp.Hi], edx {$ELSE} db D32 mov word ptr RDTSC_TimeStamp.Lo, AX db D32 mov word ptr RDTSC_TimeStamp.Hi, DX {$ENDIF} End; Result:=RDTSC_TimeStamp.Whole;End;
Это не тоже самое. А черти что и сбоку бантик. Вы возвращаете левую и скорее всего не инициируемую переменную.
Код: Выделить всё
FUNCTION HexToSymbol(b:Byte):Byte; //Простая процедура
Begin
if b<58 then HexToSymbol:=b-48;
if b>64 then HexToSymbol:=b-55;
End;В Delphi это не с компилируется.
если же убрать фц-ию HexToSymbol и оставить просто цикл, то Delphi даёт 1965 а FPC 6753.
Брехня. Если убрать то компиляторы просто выкинут цикл.
В FPC вы оптимизатор не включили. Либо забыли перекомпилить весь код, вместо этого провели его сборку.
-
Burster_TIL
- новенький
- Сообщения: 46
- Зарегистрирован: 25.09.2013 02:05:28
Pavia писал(а):Это не тоже самое. А черти что и сбоку бантик. Вы возвращаете левую и скорее всего не инициируемую переменную.
Не важно. И в FPC и Delphi RDTSC возвращает теже самые значение. Так что и там и там RDTSC работает верно.
Добавлено спустя 45 секунд:
Pavia писал(а):В Delphi это не с компилируется.
-)))) Ещё как компилируется и вполне себе работает. Не понятно, с чего эта ф-ция не будет компилироваться?-)))
Добавлено спустя 1 минуту 58 секунд:
Pavia писал(а):Брехня. Если убрать то компиляторы просто выкинут цикл.
В FPC вы оптимизатор не включили. Либо забыли перекомпилить весь код, вместо этого провели его сборку.
Если выкибывают цикл, то почему такая разница?
Компилировал стандартно Ctrl+F9. То есть компилируется и после этого запускается. Про оптимизатор не очень в курсе. Где он в этой турбовижиновской оболчке компилятора включается или конфигурируется?
Добавлено спустя 2 минуты 53 секунды:
скалогрыз писал(а):да не процедуры листинг (т.к. одинакова будет для обоих компиляторов) ,а циклов
включая реализации HEXToSymbol
Вот это я без понятия где взять и зачем. Я просто вижу факт, что в FPC цикл отрабаотывается ощутимо больше.
Burster_TIL писал(а):Компилировал стандартно Ctrl+F9. То есть компилируется и после этого запускается.
Запуск из под IDE не дает корректных результатов, т.к. запускается через отладчик. Попробуйте запустить в коммандной строке.
-
Burster_TIL
- новенький
- Сообщения: 46
- Зарегистрирован: 25.09.2013 02:05:28
MiniQ писал(а):Запуск из под IDE не дает корректных результатов, т.к. запускается через отладчик. Попробуйте запустить в коммандной строке.
Запускал просто. Не из среды. Тоже самое. При чём из Delphi запускал из-под среды, когда увидел, что такая вот удивительная разница в быстродейсвтии.
прилагаю проект.
на delphi 7
выдаёт значения около 12100
на fpc 2.6.4
без оптимизации,
выдаёт около 15200
с оптимиацией -O3 (или -O2)
выдаёт около 13100
.
Добавлено спустя 54 секунды:
Delphi листинг выглядит так. т.к. у среды проблемы с отладкой консоли, использовал objdump .
Добавлено спустя 1 минуту 52 секунды:
Листинг FPC без оптимизаций выглядит так:
Добавлено спустя 2 минуты 55 секунд:
Листинг FPC с -O3 выглядит вот так
Очевидно, что не спец-заточенность FPC под i386 добавляет чуточку лишних инструкций.
Вывод - бросать этот поганый FPC и писать под x86_64 и линуксы на Delphi 7
на delphi 7
Код: Выделить всё
dcc32 project1.dpr
выдаёт значения около 12100
на fpc 2.6.4
без оптимизации,
Код: Выделить всё
fpc project1.dpr
выдаёт около 15200
с оптимиацией -O3 (или -O2)
Код: Выделить всё
fpc -O3 project1.dpr
выдаёт около 13100
.
Добавлено спустя 54 секунды:
Delphi листинг выглядит так. т.к. у среды проблемы с отладкой консоли, использовал objdump .
Код: Выделить всё
# FUNCTION HexToSymbol(b:Byte):Byte;
# if b<58 then HexToSymbol:=b-48;
403df4: 3c 3a cmp $0x3a,%al
403df6: 73 05 jae 0x403dfd
403df8: 8b d0 mov %eax,%edx
403dfa: 80 ea 30 sub $0x30,%dl
# if b>64 then HexToSymbol:=b-55;
403dfd: 3c 40 cmp $0x40,%al
403dff: 76 05 jbe 0x403e06
403e01: 8b d0 mov %eax,%edx
403e03: 80 ea 37 sub $0x37,%dl
403e06: 8b c2 mov %edx,%eax
403e08: c3 ret
# end
...
# T1:=Get__RDTSC
403e6d: e8 7e ff ff ff call 0x403df0
403e72: 89 05 5c 56 40 00 mov %eax,0x40565c
403e78: 89 15 60 56 40 00 mov %edx,0x405660
# for i:=0 to 1000 do
403e7e: bb e9 03 00 00 mov $0x3e9,%ebx
# B:=HEXToSymbol(100);
403e83: b0 64 mov $0x64,%al
403e85: e8 6a ff ff ff call 0x403df4
403e8a: 4b dec %ebx
403e8b: 75 f6 jne 0x403e83
# T2:=Get__RDTSC
403e8d: e8 5e ff ff ff call 0x403df0
Добавлено спустя 1 минуту 52 секунды:
Листинг FPC без оптимизаций выглядит так:
Код: Выделить всё
P$PROJECT2_HEXTOSYMBOL$BYTE$$BYTE:
# Temps allocated between ebp-8 and ebp-8
# [11] Begin
pushl %ebp
movl %esp,%ebp
subl $8,%esp
# Var b located at ebp-4
# Var $result located at ebp-8
movb %al,-4(%ebp)
# [12] if b<58 then HexToSymbol:=b-48;
movzbl -4(%ebp),%eax
cmpl $58,%eax
jl .Lj7
jmp .Lj8
.Lj7:
movzbl -4(%ebp),%eax
subl $48,%eax
movb %al,-8(%ebp)
.Lj8:
# [13] if b>64 then HexToSymbol:=b-55;
movzbl -4(%ebp),%eax
cmpl $64,%eax
jg .Lj11
jmp .Lj12
.Lj11:
movzbl -4(%ebp),%eax
subl $55,%eax
movb %al,-8(%ebp)
.Lj12:
# [14] End;
movb -8(%ebp),%al
leave
ret
...
# [22] T1:=Get__RDTSC; //RDTSC_Int64;
call P$PROJECT2_GET__RDTSC$$INT64
movl %eax,U_P$PROJECT2_T1
movl %edx,U_P$PROJECT2_T1+4
# [23] for i:=0 to 1000 do
movw $0,U_P$PROJECT2_I
decw U_P$PROJECT2_I
.balign 4,0x90
.Lj19:
incw U_P$PROJECT2_I
# [25] B:=HEXToSymbol(100);
movb $100,%al
call P$PROJECT2_HEXTOSYMBOL$BYTE$$BYTE
movb %al,U_P$PROJECT2_B
cmpw $1000,U_P$PROJECT2_I
jl .Lj19
# [27] T2:=Get__RDTSC; // RDTSC_Int64;
call P$PROJECT2_GET__RDTSC$$INT64
Добавлено спустя 2 минуты 55 секунд:
Листинг FPC с -O3 выглядит вот так
Код: Выделить всё
# Temps allocated between esp+0 and esp+0
# Var b located in register al
# Var $result located in register dl
# [12] if b<58 then HexToSymbol:=b-48;
movzbl %al,%edx
cmpl $58,%edx
jnl .Lj8
movzbl %al,%edx
subl $48,%edx
.Lj8:
# [13] if b>64 then HexToSymbol:=b-55;
movzbl %al,%ecx
cmpl $64,%ecx
jng .Lj12
andl $255,%eax
subl $55,%eax
movb %al,%dl
.Lj12:
# [14] End;
movb %dl,%al
ret
...
# [22] T1:=Get__RDTSC; //RDTSC_Int64;
call P$PROJECT2_GET__RDTSC$$INT64
movl %eax,-4(%ebp)
movl %edx,%ebx
# [23] for i:=0 to 1000 do
movw $0,%si
decw %si
.balign 4,0x90
.Lj19:
incw %si
# [25] B:=HEXToSymbol(100);
movb $100,%al
call P$PROJECT2_HEXTOSYMBOL$BYTE$$BYTE
movb %al,-8(%ebp)
cmpw $1000,%si
jl .Lj19
# [27] T2:=Get__RDTSC; // RDTSC_Int64;
call P$PROJECT2_GET__RDTSC$$INT64
Очевидно, что не спец-заточенность FPC под i386 добавляет чуточку лишних инструкций.
Вывод - бросать этот поганый FPC и писать под x86_64 и линуксы на Delphi 7
У вас нет необходимых прав для просмотра вложений в этом сообщении.
скалогрыз писал(а):Вывод - бросать этот поганый FPC и писать под x86_64 и линуксы на Delphi 7
Не модно сейчас работать на ворованном.
