Битва за скорость: QLUA vs MQL5 - почему MQL5 быстрее от 50 до 600 раз?
Для сравнения языков MQL5 и QLUA мы написали несколько тестов, которые замеряют скорость выполнения базовых операций. В тестах использовался компьютер с Windows 7 Professional 64 bit, MetaTrader 5 build 1340 и QUIK версии 7.2.0.45.
Результаты представлены в таблице, где все значения представлены в миллисекундах (чем меньше время, тем лучше)
# | Название тестового скрипта | MQL5, ms | QLUA, ms | Преимущество MQL5 |
---|---|---|---|---|
1 | TestFloat | 3 969 | 273 391 | 69 раз |
2 | TestArrays | 375 | 230 768 | 615 раз |
3 | TestFibo | 1 125 | 61 110 | 55 раз |
4 | TestPiCalculated | 2 328 | 183 812 | 79 раз |
5 | TestQuickSort | 2 031 | 211 279 | 104 раза |
6 | TestAckermann | 828 | 64 541 | 78 раз |
Сравнения показывают, что MQL5 быстрее QLUA от 50 до 600 раз на базовых операциях любого языка программирования. Это достигается за счет того, что MQL5 является строго типизированным компилируемым языком в 32/64 бита в противоположность динамическому интерпретируемому QLUA.
Что это дает трейдеру? Возможность максимально быстро обсчитывать огромные массивы данных (а они в MetaTrader 5 практически не ограничены) и быстрее принимать решения.
Это всего лишь проверка базового функционала. Но за фасадом языков скрываются их API. И не у всех он простой. MQL5, будучи прикладным языком для торговой платформы, содержит в себе сотни специализированных функций по доступу/обработке рыночной информации и взаимодействию со всеми компонентами терминала.
Важно, что MQL5 не прицеплен сбоку к существующей системе, а сам является центральным звеном платформы. Все процессы в торговом терминале построены вокруг удовлетворения потребностей разработчиков торговых роботов. Это дает максимальную скорость доступа к внутренним данным платформы и прямой канал для торговых операций.TestFloat - Скорость выполнения операций с вещественными числами
Код на MQL5
//+------------------------------------------------------------------+ //| TestFloat.mq5 | //| Copyright 2016, MetaQuotes Software Corp. | //| http://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "2010, MetaQuotes Software Corp." #property link "http://www.mql5.com" //--- #define MAX_SIZE 35000 //--- double f0=0; double f1=123.456789; double f2=98765.12345678998765432; double f3=12345678943.98; //--- //+------------------------------------------------------------------+ //| Функция OnStart | //+------------------------------------------------------------------+ int OnStart() { uint tick_count,res; //--- тест tick_count=GetTickCount(); TestFloat(); res=GetTickCount()-tick_count; Print("Test float time=",res," ms"); Print("Result=",f0); //--- возвращает время, затраченное на выполнение теста, в милисекундах return((int)res); } //+------------------------------------------------------------------+ //| Функция тестирования | //+------------------------------------------------------------------+ void TestFloat() { for(int i=0;i<MAX_SIZE;i++) for(int j=0;j<MAX_SIZE;j++) { f0=f0+(f1/(i+1))-f2+(f3*i); } } //+------------------------------------------------------------------+
Код на LUA
-- TestFloat f0=0.0 f1=123.456789 f2=98765.12345678998765432 f3=12345678943.98 MAX_SIZE=35000 function Start() local t=os.clock() TestFloat() local res=(os.clock()-t)*1000 -- результы выполнения занесем сюда check=f0 message("TestFloat time=" ..res.." ms\n check="..tostring(check)); end function TestFloat() -- в цикле мы проходим до значение на 1 меньше, чем MAX_SIZE MAX_SIZE=MAX_SIZE-1 for i=0, MAX_SIZE do for j=0, MAX_SIZE do f0=f0+(f1/(i+1))-f2+(f3*i); end end end -- запускаем скрипт Start()
TestArrays - Тестирование времени доступа к элементам массива
Код на MQL5
//+------------------------------------------------------------------+ //| TestArrays.mq5 | //| Copyright 2016, MetaQuotes Software Corp. | //| http://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "2010, MetaQuotes Software Corp." #property link "http://www.mql5.com" //--- #define MAX_SIZE 32000 //--- int x[MAX_SIZE],y[MAX_SIZE]; //+------------------------------------------------------------------+ //| Функция OnStart | //+------------------------------------------------------------------+ int OnStart() { int i,k; uint tick_count,res; //--- тест tick_count=GetTickCount(); for(i=0;i<MAX_SIZE;i++) x[i]=i+1; for(k=0;k<MAX_SIZE;k++) for(i=MAX_SIZE-1; i>=0; i--) y[i]+=x[i]; long check=0; for(i=0;i<MAX_SIZE;i++) { check+=y[i]; } res=GetTickCount()-tick_count; Print("TestArrays time=",res," ms"); Print("check=",check); //--- возвращает время, затраченное на выполнение теста, в милисекундах return((int)res); } //+------------------------------------------------------------------+
Код на LUA
-- TestArrays function Start() MAX_SIZE=32000 x={} y={} local start=os.clock() for i=1,MAX_SIZE,1 do x[i]=i y[i]=0 end y[MAX_SIZE]=0 for k=1,MAX_SIZE,1 do for i=MAX_SIZE, 1,-1 do y[i]=y[i]+x[i] end end local res=(os.clock()-start)*1000 -- контрольное число local check=0 for k=1,MAX_SIZE,1 do check=check+y[k] end message("Time = "..res.." ms\n check=".. check) end -- запускаем скрипт Start()
TestFibo - вычисление последовательности ряда Фибоначии
Код на MQL5
//+------------------------------------------------------------------+ //| TestFibo.mq5 | //| Copyright 2010, MetaQuotes Software Corp. | //| http://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "2010, MetaQuotes Software Corp." #property link "http://www.mql5.com" //--- #define MAX_SIZE 40 long fib[MAX_SIZE]; //+------------------------------------------------------------------+ //| Функция OnStart | //+------------------------------------------------------------------+ void OnStart() { int i; uint res; //--- тест res=GetTickCount(); for(i=0;i<MAX_SIZE;i++) fib[i]=TestFibo(i); res=GetTickCount()-res; Print("TestFibo time=",res," ms"); Print("Fibo[39]=",fib[39]); } //+------------------------------------------------------------------+ //| Функция тестирования | //+------------------------------------------------------------------+ long TestFibo(long n) { if(n<2) return(1); //--- return(TestFibo(n-2)+TestFibo(n-1)); } //+------------------------------------------------------------------+
Код на LUA
-- TestFibo MAX_SIZE=40 fib={} function Start() start=os.clock() for i=0,MAX_SIZE-1 do fib[i]=TestFibo(i) end res=(os.clock()-start)*1000 message("TestFibo time="..res.." ms\n Fibo[39]="..fib[39]) end function TestFibo(n) if n<2 then return(1) else return(TestFibo(n-2)+TestFibo(n-1)) end end -- запускаем скрипт Start()
TestPiCalculated - Вычисление 22 000 знаков числа Pi
Код на MQL5
//+------------------------------------------------------------------+ //| TestPiCalculated.mq5 | //| Copyright 2016, MetaQuotes Software Corp. | //| http://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "2010, MetaQuotes Software Corp." #property link "http://www.mql5.com" //--- #define MAX_SIZE 22000 //--- в эту строку поместим значение числа PI string str; int a[(MAX_SIZE/4+1)*14]; //+------------------------------------------------------------------+ //| Функция OnStart | //+------------------------------------------------------------------+ int OnStart() { uint tick_count,res; //--- тест tick_count=GetTickCount(); PiCalculate(MAX_SIZE); res=GetTickCount()-tick_count; Print("TestPiCalculated time=",res," ms"); Print("Pi=",StringSubstr(str,0,16)); //--- возвращает время, затраченное на выполнение теста, в милисекундах return((int)res); } //+------------------------------------------------------------------+ //| Функция тестирования | //+------------------------------------------------------------------+ void PiCalculate(const int digits) { int d = 0,e,b,g,r; int c = (digits/4+1)*14; int f = 10000; //--- for(int i=0;i<c;i++) a[i]=20000000; //--- while((b=c-=14)>0) { d=e=d%f; while(--b>0) { d = d * b + a[b]; g = (b << 1) - 1; a[b]=(d%g)*f; d/=g; } r=e+d/f; if(r<1000) { if(r>99) str+="0"; else { if(r>9) str+="00"; else str+="000"; } } str+=IntegerToString(r); } } //+------------------------------------------------------------------+
Код на LUA
-- TestPiCalculated -- сколько знаков числа Pi будем вычислять MAX_SIZE=22000 -- в эту строку поместим значение числа Pi str="" a={} function OnStart() start=os.clock() PiCalculate(MAX_SIZE) -- время вычисления числа Pi в миллисекундах res=(os.clock()-start)*1000 message("TestPiCalculated time=" .. res .." ms\n\n Pi="..string.sub(str,1,16)) -- выведем 16 знаков end function PiCalculate(digits) d = 0 c = (math.floor(digits/4)+1)*14 -- math.floor() -целочисленное деление на основе примера из справки LUA f = 10000 for i=0,c do a[i]=20000000 end c=c-14 b=c while b>0 do e=d%f d=e while b-1>0 do b=b-1 d = d * b + a[b] g = (b * 2) - 1 a[b]=(d%g)*f d=math.floor(d/g) -- math.floor(d/g) -целочисленное деление на основе примера из справки LUA end r=e+math.floor(d/f) -- math.floor(d/f) - это целочисленное деление на основе примера из справки LUA if r<1000 then if(r>99) then str=str .. "0" else if(r > 9) then str=str .. "00" else str=str .. "000" end end end str=str .. string.format("%d",r) c=c-14 b=c end end -- запускаем скрипт OnStart()
Тестирование времени быстрой сортировки массива
Код на MQL5
//+------------------------------------------------------------------+ //| TestQuickSort.mq5 | //| Copyright 2016, MetaQuotes Software Corp. | //| http://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "2010, MetaQuotes Software Corp." #property link "http://www.mql5.com" //--- будем сортировать массив размером в 16 миллионов элементов #define MAX_SIZE 16000000 //--- int array[MAX_SIZE]; //+------------------------------------------------------------------+ //| Функция OnStart | //+------------------------------------------------------------------+ void OnStart() { uint tick_count,res; for(int i=0;i<MAX_SIZE;i++) array[i]=i%100; tick_count=GetTickCount(); QuickSort(array,0,MAX_SIZE-1); res=GetTickCount()-tick_count; Print("TestQuickSort time=",res," ms"); for(int i=1;i<MAX_SIZE;i++) if(array[i]<array[i-1]) { Print("Array not sorted"); break; } } //+------------------------------------------------------------------+ //| Функция быстрой сортировки | //+------------------------------------------------------------------+ void QuickSort(int &arr[],int left,int right) { int i=left; int j=right; int center=arr[(i+j)/2]; int x; //--- while(i<=j) { while(arr[i]<center && i<right) i++; while(arr[j]>center && j>left) j--; if(i<=j) { x=arr[i]; arr[i]=arr[j]; arr[j]=x; i++; j--; } } if(left<j) QuickSort(arr,left,j); if(right>i) QuickSort(arr,i,right); } //+------------------------------------------------------------------+
Код на LUA
-- TestQuickSort -- будем сортировать массив размером в 16 миллионов элементов MAX_SIZE=16000000 array={} function Start() for i=0,MAX_SIZE-1 do array[i]=i%100 end start=os.clock() QuickSort(array,0,MAX_SIZE-1) res=(os.clock()-t)*1000 message("TestQuickSort time=" .. res .. " ms") for i=1,MAX_SIZE-1 do if array[i]<array[i-1] then message("Array not sorted"); break; end end end function QuickSort(arr,left,right) i=left j=right center=arr[math.floor((i+j)/2)] while i<=j do while(arr[i]<center and i<right) do i=i+1 end while(arr[j]>center and j>left) do j=j-1 end if i<=j then x=arr[i] arr[i]=arr[j] arr[j]=x i=i+1 j=j-1 end end if left<j then QuickSort(arr,left,j) end if right>i then QuickSort(arr,i,right) end end -- запускаем скрипт Start()
TestAckermann - тестирование рекурсии в функциях
Код на MQL5
//+------------------------------------------------------------------+ //| TestAckermann.mq5 | //| Copyright 2016, MetaQuotes Software Corp. | //| http://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "2016, MetaQuotes Software Corp." #property link "http://www.mql5.com" //--- количество прогонов функции Аккермана в цикле #define MAX_SIZE 120000 //+------------------------------------------------------------------+ //| Функция OnStart | //+------------------------------------------------------------------+ void OnStart() { //--- контрольное число uint check=0; //--- время выполнения в миллисекундах uint res=0; //--- тест res=GetTickCount(); for(int i=0;i<MAX_SIZE;i++) check+=Ackermann(1+i%3,1+i%5); res=GetTickCount()-res; Print("TestAckermann time=",res," ms"); Print("check=",check); //--- } //+------------------------------------------------------------------+ //| Функция тестирования | //+------------------------------------------------------------------+ int Ackermann(int m,int n) { if(m==0) return(n+1); if(n==0) return(Ackermann(m-1,1)); //--- return(Ackermann(m-1,Ackermann(m,(n-1)))); } //+------------------------------------------------------------------+
Код на LUA
-- TestAckermann MAX_SIZE=120000 function Start() local check=0 -- контрольное число local start=os.clock() for i=1,MAX_SIZE do check=check+Ackermann(1+i%3,1+i%5); end local finish=os.clock() local time=(finish-start)*1000 message("TestAckermann time=".. time.." ms\n\n check="..check) end function Ackermann(m,n) if(m==0) then return(n+1) end if(n==0) then return(Ackermann(m-1,1)) end return(Ackermann(m-1,Ackermann(m,(n-1)))) end -- запускаем скрипт Start()
Полный архив скриптов можно скачать и проверить результаты самостоятельно.
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Так вроде компилируемый код всегда во много раз быстрее интерпретируемого. Или бывают исключения?