Может что-то добавить в тест, например вызов функций или еще чего :)
В MQL4 очень эффективный компилятор в p-код и еще более эффективная виртуальная
машина исполненения(написана на ассемблере).
Упор делался на проверку базовой математики - циклов и простейших вычислений.
Вызов функций в MQL4 тоже очень быстрый.
DefineDLLfunc:"Kernel32.dll",INT, "GetTickCount"; Variable : res_int(0),i(0),start_time(0),res_double(0); res_int=0; res_double=0; start_time=GetTickCount(); for i=0 to 10000000 begin res_int=res_int+i*i; res_int=res_int+1; res_double=res_double+i*i; res_double=res_double+1; end; start_time=GetTickCount()-start_time; Alert("Time: "+NumToStr(start_time,0)+" ms, ResInt="+NumToStr(res_int,0)+" ResDouble="+ NumToStr(res_double,0));
Для замеров времени используется таже самая стандартная функция GetTickCount(), импортируемая из kernel32.dll . И результат:
Easy: Time: 875 ms, ResInt=3369844457615319400 ResDouble=3369844457615319400
Поместим в общую таблицу:
VC++: Time: 47 ms, ResInt=-752584127 ResDouble=17247836076609 MQL4: Time: 797 ms, ResInt=-752584127 ResDouble=17247836076609 Easy: Time: 875 ms, ResInt=3369844457615319400 ResDouble=3369844457615319400 MQL2: Time: 22156 ms, ResInt=333333383333717340000 ResDouble=333333383333717340000 WL3 : Time: 32422 ms, ResInt=3.33333383333717E20 ResDouble=3.33333383333717E20
EasyLanguage показал достойный результат по скорости, но вот что-то у него не сложилось с точностью вычислений. Похоже что на каком-то этапе у него происходит переполнение. Если же уменьшить количество циклов (например, до 10000), то все расчеты у всех 5ти языков сходятся. Если кто-то найдет ошибку в коде - укажите, пожалуйста.
Через некоторое время мы представим обзорную статью с тестами языков еще нескольких систем. Естественно, тестовые примеры будут расширены. Если есть предложения - что именно (какие операции и функции) нужно протестировать, то пишите - согласуем тестовые примеры. Желательно чтобы код был универсальным и реализуемым в разных системах.
Приведённые результаты можно считать верными только в том случае, когда на тестовой машине не исполнялась ни одна другая задача и приоритет выполняемого процесса был поднят до time critical. Будем надеятся, что так оно и было, однако, Ренат, если не трудно, приведи результаты тестов с использованием функции clock для замера времени.
Я все таки знаю условия соблюдения чистоты экспериментов. Замеры были проведены многократно и с практически одинаковыми результатами (погрешность на уровне 10-15 ms, чем можно явно пренебречь когда итоговые цифры 800, 22000 и 32000). В тестах важно было сделать общий обзор скорости исполнения. Тиковый счетчик можно использовать разве что для замера скорости выполнения VC++ кода, но с VC++ кодом все понятно.
Результатом стало:
1) MQL4 и Easy показали практически один результат, что говорит об одинаковом качестве скомпилированного кода и виртуальной машине исполнения. Это достаточно эффективные компиляторы.
2) MQL2 и WL3 по сути являются интерпретаторами, что сильно сказывается на скорости выполнения
3) Easy выдал ошибочный результат из-за переполнений (при меньшем счетчике все выдавал правильно)
Именно трудно - откуда ее взять в этих языках? К счастью, clock совсем не нужен - достаточно поднять объем вычислений чтобы воспользоваться более грубым счетчиком.
res_int=0; start_time=0; res_double=0; //---- start_time=GetTickCount(); for(i=0;i<=10000000;i++) { res_int=res_int+i*i; res_int++; res_double=res_double+i*i; res_double++; } start_time=GetTickCount()-start_time; //---- вывод результатов в окно Interpretation str="Time: "+start_time+" ms, ResInt="+res_int+" ResDouble="+res_double;
Так как AmiBroker не содержит в себе функций замера скорости, то пришлось написать простую DLL c функцией, выдающей результат от штатной GetTickCount.
Вот результаты:
Ami : Time: 12626 ms, ResInt=3.36984e+020 ResDouble=3.36984e+020
Результаты математических вычислений опять отличаются - даже странно.
Кто-нибудь сможет найти ошибку?
Эталоном расчетов является следующий код на VC++ (за правильный результат ручаюсь):
void main() { double res_int=0,i; int start_time; double res_double=0; //---- start_time=GetTickCount(); for(i=0;i<=10000000;i++) { res_int+=i*i; res_int++; res_double+=i*i; res_double++; } start_time=GetTickCount()-start_time; //---- printf("Time: %d ms, ResInt=%lf ResDouble=%lf\n",start_time,res_int,res_double); }
с результатом вычислений: ResDouble=333333383333717340000
И итоговое распределение мест:
VC++: Time: 47 ms, ResInt=-752584127 ResDouble=17247836076609 MQL4: Time: 797 ms, ResInt=-752584127 ResDouble=17247836076609 Easy: Time: 875 ms, ResInt=3369844457615319400 ResDouble=3369844457615319400 Ami : Time: 12626 ms, ResInt=3.36984e+020 ResDouble=3.36984e+020 MQL2: Time: 22156 ms, ResInt=333333383333717340000 ResDouble=333333383333717340000 WL3 : Time: 32422 ms, ResInt=3.33333383333717E20 ResDouble=3.33333383333717E20
Результаты математических вычислений опять отличаются - даже странно.
Кто-нибудь сможет найти ошибку?
Overflow in conversion or arithmetic operation
Ренат, я не отрицал твоей компетентности, более того, считаю, что человек занятый в таком серьёзном проекте не может этого не знать. Просто я сам не раз сталкивался с не совсем адекватным поведением GetTickCount(); Хотя, если результаты множества замеров были устойчивыми +/- некоторая маленькая дельта, то это подтверждает верность тестов.
Либо сразу импортировать из msvcrt.dll либо написать свою dll - wrapper.
Ну да ладно, я согласен, что результаты достаточно точные, а главное показательные.
Вообще-то переполнения должны быть арифметически "правильными/предсказуемыми", но не
"результат неопределен". Да, зачастую в документации именно так и пишется "результат неопределен", но результат предсказуем.
VC++(счетчик в double), MQL2, MQL4(счетчика в double) дают правильный результат
ResDouble=333333383333717340000
WL3 - правильно с маленькой погрешностью ResDouble=3.33333383333717E20
А EasyLanguage и AmiBroker - совершенно левый результат.
Пример для тестов был взят совершенно простой, но вылезшие расхождения оказались интересными - поэтому я не стал переделывать тестовый код. В следующих тестах будет подобран код с результатами без переполнений. Планируется сделать серию тестов по работе с различными данными: обычные мат операции, циклы, работа с массивами, доступ к рабочим графикам, вызов функций.
Да, точность GetTickCount() прыгает от 10 до 16 мс и им нельзя мерить мелкие периоды, но в нашем случае его использование обосновано. Особенно, когда к нему так легко достучаться из почти любого кода.
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Идея - в 10 миллионном цикле добавляем в целочисленную переменную квадрат переменной цикла с последующим увеличением на единицу и в тоже самое в переменную с плавающей запятой.
В качестве замера времени используем штатную Windows функцию GetTickCount(), которая возвращает количество миллисекунд с момента запуска сессии Windows. Точности счетчика (миллисекунды) достаточно для замеров.
Тесты для общей информации о производительности языков.
Код на VC++ 6.0 (максимальная оптимизация, однопотоковая библиотека)
Код на MQL4 (практически 100% совпадает с кодом VC С++)
Код на MQL2 (при тестировании был отключен 1 секундный контроль)
Код на Wealth-Lab Script 3.0:
Тестирование проводилось на компьютере Intel P4, 2.8Ghz(HT), RAM 1Gb.
Результаты:
На этих тестах видно, что MQL4 отстает от чистого кода VC++ в 17 раз.
MQL2 отстает от MQL4 в 27 раз и в 471 раз от VC++.
WL3 отстает от MQL4 в 40 раз и в 690 раз от VC++.
MQL4 и VC++ выдают один результат вычислений (правильный, с учетом типов переменных int и double).
MQL2 и WL3 выдают другой результат, так как у них все переменные всегда с плавающей запятой.
В расчетах индикаторов и экспертов очень часто используются циклы и другие целочисленные операции. Автоматическое использование всех переменных как double обходится очень дорого если думать о производительности.
Но протестируем производительность MQL4, когда все переменные с плавающей запятой? Вот код:
И результат:
Результаты совпадают с результатами MQL2 и WL3, а замедление исполнения по сравнению
с целочисленными счетчиками составило 13%.
Любой может повторить тесты (только в MQL2 есть ограничение в максимальное время 1 сек).