Форум » Для флейма » Интерпретаторы » Ответить

Интерпретаторы

Pasha: Возьмем 3 продукта: 1с 8, visual foxpro и harbour. Назначение у них различное, коня и трепетную лань сравнивать не стоит, но есть и кое-что общее: все они имеют интерпретатор, построенный на похожем принципе: сначала делается предкомпиляция в некий промежуточный код, а затем этот код выполняется. Поэтому возникла мысль сравнить производительность этих интерпретаторов, посмотреть, так сказать, чей движок мощнее. Берем простенький тест: func main Local i, nLoops := 5000000 Local L_F := 112345.67 Local L_N := 10000 Local L_C := "0123456789ABCDEF" Local nn, nf, cc Local nn1 := 0 Local nf1 := 0.1 Local cc1 := "" Local nn2, nf2 Local nSec := Seconds() for i := 1 to nLoops nn := L_N nf := L_F cc := L_C nn := L_N + 1 nf := L_F + 1.0 cc := L_C + L_C nn1 += L_N + 1 nf1 += L_F + 1.0 if (nn1 % 2) == 0 // cc1 += L_C + chr(nn1 % 256) endif if (len(cc1) % 3) == 0 nn2 := nn1 % 13 nf2 := nf1 % 13 endif nn := (nn1 + L_N + 1)*100/15 nf := (nf1 + L_F + 1.0)*100.00/15.00 next ? Seconds() - nSec ? nn, nf, cc ? nn1, nf1, len(cc1) ? nn2, nf2 retu nil И запускаем его, с учетом различия в синтаксисе языков, конечно. Компьютер: Celeron 2.5 GHZ, 1GB RAM Закомментаренный оператор - это конкатенация строк. Сразу скажу, что с конкатенацией не справился никто, кроме, естественно, харбора. Да и на его результате конкатенация сказалась незначительно: Время с конкатенацией 18.59 сек Время без конкатенации 16.86 сек foexpro показал вполне приличный результат - 48.08 сек, что всего лишь в три раза хуже харбора. Ну а что же хваленые канадские профессионалы 1с ? Ждать пришлось долго, 330 сек, что в 20(!) раз хуже харбора. Здесь даже не подходит аналогия сравнения двигателя Запорожца с двигателем Ламборджини, надо сравнивать с двигателем реактивного истребителя. Как говорится, за много-много лет ничто не мешало 1с обзавестись приличным движком, да вот как-то не сложилось. Ну а движок харбора порадовал, хорош. Можно было протестировать продукты и на других режимах, скажем, добавить тест ООП, но, думается, смысла в этом нет, класс уже понятен и без этого.

Ответов - 33, стр: 1 2 All

AlexMyr: Pasha пишет: Прогнал свой тест на java можно исходник адаптированный для java?

Dima: Pasha пишет: Прогнал свой тест на java Пробни еще Perl , думаю он будет еще быстрее.

Pasha: AlexMyr пишет: можно исходник адаптированный для java? Да, конечно. Конкатенацию строк я опять убрал, java с ней не справляется. package javaapplication1; public class JavaApplication1 { public static void main(String[] args) { int i; int nLoops = 5000000; double L_F = 112345.67; int L_N = 10000; String L_C = "0123456789ABCDEF"; long nn; double nf; String cc; long nn1 = 0; double nf1 = 0.1; String cc1 = ""; long nn2; double nf2; for( i = 1; i <= nLoops; i++ ) { nn = L_N; nf = L_F; cc = L_C; nn = L_N + 1; nf = L_F + 1.0; cc = L_C + L_C; nn1 += L_N + 1; nf1 += L_F + 1.0; if( (nn1 % 2) == 0 ) { // cc1 += L_C + "0"; //+ nn1.toString(256); } if( (cc1.length() % 3) == 0 ) { nn2 = nn1 % 13; nf2 = nf1 % 13; } nn = (nn1 + L_N + 1)*100/15; nf = (nf1 + L_F + 1.0)*100.00/15.00; } System.out.println("Hello"); System.out.println(nn1); System.out.println(nf1); } }


Pasha: Еще пару слов о фокспро. За примерно 10 лет от vfp6 до vfp9sp2 его движок потерял в "мощности" примерно 10%. Тест конечно очень условный, я его набросал на скорую руку, просто для того, чтобы выстроить продукты по рангу.

AlexMyr: Pasha пишет: Да, конечно. Конкатенацию строк я опять убрал, java с ней не справляется. спасибо, попробую.

AlexMyr: На домашнем ноуте такой результат: java: пришлось поправить первые строки package javaapplication1; public class JavaApplication1 { public static void main(String[] args) { Hello 50005000000 5.61733349977449E11 harbour: 14.60

Петр: AlexMyr пишет: harbour: 14.60 Для java добавьте в код long nBegin = System.currentTimeMillis(), nEnd; .. nEnd = System.currentTimeMillis(); System.out.println( (nEnd - nBegin) / 1000.0 );

Петр: Не знаю почему, но мне понравилась идея сравнения Java c Harbour, нет не вообще (тут все понятно - масштабы конечно не те), а именно выполнения конкретного кода. Для начала я скачал и установил Java SE 7u2 (JDK 7) и чуть поправил код от Pasha [pre2]/*jtest.java*/ import static java.lang.System.out; public class jtest { public static void main(String[] args) { final int nLoops = 5000000; final double L_F = 112345.67; final int L_N = 10000; final String L_C = "0123456789ABCDEF"; String cc = ""; long nn = 0; double nf = 0.0; long nn1 = 0; double nf1 = 0.1; StringBuilder cc1 = new StringBuilder(65536); long nn2 = 0; double nf2 = 0.0; long tB; out.printf("%s %s %s %s %s\n", System.getProperty("java.vm.vendor"), System.getProperty("java.vm.name"), System.getProperty("java.version"), System.getProperty("os.name"), System.getProperty("os.arch")); tB = System.currentTimeMillis(); for( int i = 1; i <= nLoops; i++ ) { nn = L_N; nf = L_F; cc = L_C; nn = L_N + 1; nf = L_F + 1.0; cc = L_C + L_C; nn1 += L_N + 1; nf1 += L_F + 1.0; if( nn1 % 2 == 0 ) { cc1.append(L_C).append( (char) (nn1 % 256) ); } if( cc1.length() % 3 == 0 ) { nn2 = nn1 % 13; nf2 = nf1 % 13; } nn = (nn1 + L_N + 1) * 100/15; nf = (nf1 + L_F + 1.0) * 100.00/15.00; if( i % 1000000 == 0 ) { out.printf("%d\n", nLoops-i); } } out.println(""); out.printf("%.2f\n", (System.currentTimeMillis() - tB) / 1000.0); out.printf("%d\n", nLoops); out.println(""); out.printf("%d %.3f %s\n", nn, nf, cc); out.printf("%d %.3f %d\n", nn1, nf1, cc1.length()); out.printf("%d %.6f\n", nn2, nf2); } } [/pre2]А затем с помощью скрипта (будете копировать - помните о концевых пробелах, да и начальных - тоже) [pre2]rem jtest.bat @ECHO OFF IF NOT DEFINED "%JDK_HOME%" SET JDK_HOME="C:\Program Files\Java\jdk1.7.0_02" @%JDK_HOME%\bin\javac -Xlint jtest.java @%JDK_HOME%\bin\jar -vcfe apptest.jar jtest jtest.class @%JDK_HOME%\bin\jar -i apptest.jar @%JDK_HOME%\bin\java -Xint -Xincgc -Xms512m -Xmx512m -jar apptest.jar [/pre2]запустил его на исполнение.

Петр: Получил такой вот результат [pre2]Oracle Corporation Java HotSpot(TM) Client VM 1.7.0_02 Windows XP x86 8,63 5000000 333366733340 3744889748827,460 0123456789ABCDEF0123456789ABCDEF 50005000000 561733349977,449 42500000 3 6,778931 [/pre2] Немного о параметрах запуска -Xint - Java HotSpot VM работает в режиме интерпретатора (байт кода), режим не основной - отключает JIT и прочие фирменные ухищрения Sun -Xincgc - включить инкрементальный сборщик мусора -Xms512m -Xmx512m - установить начальный и максимальный размер кучи памяти равным 512 Mb (у Java апетит на память хороший ). Если -Xint упустить или использовать -Xmixed, результат будет другой [pre2]Oracle Corporation Java HotSpot(TM) Client VM 1.7.0_02 Windows XP x86 1,73 5000000 333366733340 3744889748827,460 0123456789ABCDEF0123456789ABCDEF 50005000000 561733349977,449 42500000 3 6,778931 [/pre2]

Петр: Теперь перейдем к Harbour. Выполнялся вот такой код от Pasha [pre2] #translate printf( [<explist,...>] ) => QOut( hb_strFormat(<explist>) ) #translate println( [<explist,...>] ) => QOut( <explist> ) #define N_LOOPS 5000000 #define L_F 112345.67 #define L_N 10000 #define L_C "0123456789ABCDEF" FUNCTION main() LOCAL cc LOCAL nn LOCAL nf LOCAL nn1 := 0 LOCAL nf1 := 0.1 LOCAL cc1 := "" LOCAL nn2 LOCAL nf2 LOCAL tB LOCAL i QQOut( hb_Version(), hb_Version(11), hb_Version(1), hb_Version(21) ) tb := hb_SecondsCPU() FOR i := 1 to N_LOOPS nn := L_N nf := L_F cc := L_C nn := L_N + 1 nf := L_F + 1.0 cc := L_C + L_C nn1 += L_N + 1 nf1 += L_F + 1.0 IF nn1 % 2 == 0 cc1 += L_C + chr(nn1 % 256) END IF Len(cc1) % 3 == 0 nn2 := nn1 % 13 nf2 := nf1 % 13 END nn := (nn1 + L_N + 1) * 100/15 nf := (nf1 + L_F + 1.0) * 100.00/15.00 IF i % 1000000 == 0 printf( "%d", N_LOOPS - i ) END NEXT println() printf("%.2f", hb_SecondsCPU() - tb) printf("%d", N_LOOPS) println() printf("%d %.3f %s", nn, nf, cc) printf("%d %.3f %d", nn1, nf1, Len(cc1)) printf("%d %.6f", nn2, nf2) RETURN NIL [/pre2]

Петр: Harbour был собран для компилятора MinGW 4.6.1 и VC 16 (из состава MSVC 2010) (HB_USER_CFLAGS=-DHB_GC_AUTO) В принципе по результатам выполнения speedtst, всегда лучшим был VC. Но после выхода MinGW 4.6.x разницой в 0.25 - 1 сек можно принебречь. Компилируем hbmk2 jtest.prg -st и запускаем. Получаем такой вот результат [pre2]Harbour 3.1.0dev (Rev. 17173) Jan 2 2012 18:44:16 MinGW GNU C 4.6.1 (32-bit) WIN 13.16 5000000 333366733340 3744889748827.460 0123456789ABCDEF0123456789ABCDEF 50005000000 561733349977.449 42500000 3 6.778931 Harbour 3.1.0dev (Rev. 17173) Jan 2 2012 18:12:19 Microsoft Visual C++ 16.0.30319 (32-bit) WIN 15.30 5000000 333366733340 3744889748827.460 0123456789ABCDEF0123456789ABCDEF 50005000000 561733349977.449 42500000 3 6.778931[/pre2]Т.е. получается Java HotSpot(TM) где-то в 1,5-1,7 раза быстрее в режиме интерпретатора байт-кода.

Петр: Теперь компилируем hbmk2 jtest.prg -st /gc3 и снова запускаем. Смотрим результат [pre2]Harbour 3.1.0dev (Rev. 17173) Jan 2 2012 18:44:16 MinGW GNU C 4.6.1 (32-bit) WIN 7.22 5000000 333366733340 3744889748827.460 0123456789ABCDEF0123456789ABCDEF 50005000000 561733349977.449 42500000 3 6.778931 Harbour 3.1.0dev (Rev. 17173) Jan 2 2012 18:12:19 Microsoft Visual C++ 16.0.30319 (32-bit) WIN 9.50 5000000 333366733340 3744889748827.460 0123456789ABCDEF0123456789ABCDEF 50005000000 561733349977.449 42500000 3 6.778931 [/pre2] Все таки есть у HotSpot(TM) свои фишки - 4,1-5,5 Заметили, MinGW быстрее? Что-то я расписался здесь, но ведь флейм же Кстати, тестировалось на машине с процессором AMD Athlon X2 64 Dual 3600+ (2,01 ГГц), ОЗУ 1 Гб DDR2.

Pasha: Про JIT я тоже сразу сообразил, что такое сравнение с харбором не совсем корректно, но как отключить его не увидел Я пользовался netbeans. и jre6 от sun, а там такого ключика не увидел. Получается, как интерпретаторы java и harbour находятся примерно на одном уровне, а в режиме реального кода java все-таки намного быстрее. Резервы у harbour конечно еще есть. Я думаю, в режиме -gc3 надо исключать работу со стеком. Частично это уже сделано, это т.н. multi PCODE operations. Я попробовал в таком же духе изменить операцию вида Field->FName := uLocalVar Такой тест: Local nLoops := 5000000 Local nVar1 := 1 Local nVar1 := 2 Local nVar1 := 3 Local nVar1 := 4 for i := 1 to nLoops Field->F1 := nVar1 Field->F1 := nVar2 Field->F1 := nVar3 Field->F1 := nVar4 next показал увеличение производительности примерно на 5% Можно было бы оптимизировать в таком же духе все команды HB_P_JUMP* после операций сравнения: Вместо if( hb_xvmGreater() ) break; if( hb_xvmPopLogical( &fValue ) ) break; if( !fValue ) goto lab00001; Компилировать код в if( hb_xvmNewGreater( &fValue ) ) break; if( !fValue ) goto lab00001; и так далее Но у Przemeka в todo list есть такой пункт: % rewrite compiler internal logic to not generate PCODE online but use some meta code (expression list) and introduce new multiline optimizations using above meta code. Наверное, это какое-то радикальное решение.



полная версия страницы