Dear developers, could you please inform me how MQL_MEMORY_USED is calculated?
I made a calculation of memory that all EA variables occupy.
It is less than 10%. If I understand it correctly, MQL_MEMORY_USED contains the History cache and CopyTicks cache. But it is still much less.
At the same time, the parallel Expert Advisor consumes several times less. But the principle is the same.
In general, what is included to this value?
I have saved a template with Expert Advisor and applied it to the same chart by causing reloading. I have seen it like this.
The memory usage has changed by almost an order of magnitude. So far, it is difficult to explain what it means.
Many programs have cumulative effect of memory usage. This is a sin of browsers and sometimes even Word. The Terminal may also be guilty of it. Besides, all logs are written by default and it's easy to spend a week if you have too many actions in one giga. This is an evil which must be managed. But it is not clear how.
Making a trivial Market product in the form of a Market Screener is actually not an achievable task for the MT5 due to excessive memory consumption.
The terminal eats so much memory after launching.
After execution of the screener it started to eat 2 gigs (TERMINAL_MEMORY_USED and did not decrease with time). This is with only one open chart for 5000 M1-bars.
Did not save a screenshot. But decided to throw in an example, which shows memory eating Terminal not in itself, where it's just stupid.
// Создание копий оригинальных символов из Обзора рынка в виде пользовательских.#property script_show_inputsinputdatetime inStartTime = D'2020.06.01'; // С какого времени закачивать тикиvoidOnStart()
{
for (int i = SymbolsTotal(true) - 1; !IsStopped() && (i >= 0); i--)
{
conststring Symb = SymbolName(i, true);
if (!SymbolInfoInteger(Symb, SYMBOL_CUSTOM)) // Если символ не кастомный.
{
Alert(Symb + " - Start.");
MqlTick Ticks[];
if (CopyTicksRange(Symb, Ticks, COPY_TICKS_ALL, (long)inStartTime * 1000) > 0) // Взяли с него тики.
{
conststring CustomSymb = "CUSTOM_" + Symb;
if (SymbolInfoInteger(CustomSymb, SYMBOL_EXIST) || CustomSymbolCreate(CustomSymb, AccountInfoString(ACCOUNT_SERVER), Symb)) // Содали кастомный.
{
Alert((string)i + ": " + Symb + " - " + (string)CustomTicksReplace(CustomSymb, 0, LONG_MAX, Ticks)); // Поместили в него тики.SymbolSelect(CustomSymb, true);
}
}
}
}
}
The script just makes copies of the original symbols from the Market Watch. I was supposed to add all the symbols on MQ-Demo and run this script first time on cold and then again on hot.
And after the hot run (when the ticks are already on SSD in the form of tkc-files) I will observe enormous memory exhaustion where it's not needed in a proper implementation.
However, running the script, I've encountered that it hangs on MQ-Demo. It can be unloaded only through Abnormal termination, after which the Terminal will not release more than 1 GB of memory.
It's easy to compare this screenshot with the one in the beginning.
Sorry, not sure if this is a bug or a feature. I haven't found an answer on my own. But the question is related to performance and I suppose it's better to ask it here.
If I add, for example, 22 buffers of DRAW_SECTION type to an empty indicator, then at startup of such an indicator for one chart containing 1000000 bars or more the terminal lags significantly (it causes significant CPU load) and eats significant amounts of memory, even if the indicator calculates nothing.
My interest was aroused by the fact that if you use buffers with other types, everything works without problems and such slowdown is not observed.
For example, I executed the following code on a single chart with 1000000 bars and it consumed about 500 MBytes and lags, especially the chart itself.
But if I change the buffers type to, say, DRAW_LINE, the load on the processor is reduced dramatically, lags are not observed, and memory consumes 5 times less (about 100 MBytes consumed).
An individual citizen pulled outa duplicate of an invaluable load of MQL code from his wide trousers, which showed that under the same conditions the crutch worked faster than the regular function.
A very simple test:
//+------------------------------------------------------------------+//| |//+------------------------------------------------------------------+voidOnTick()
{
TestSymbolInfoTick();
TestPositionSelectByTicket();
}
//+------------------------------------------------------------------+//| |//+------------------------------------------------------------------+void TestSymbolInfoTick()
{
MqlTick Tick;
//---ulong start,end,max_time=0,avr_time=0,counter=0;
int count=100000;
for(int i=0; i<count; i++)
{
start=GetMicrosecondCount();
SymbolInfoTick(_Symbol, Tick);
end=GetMicrosecondCount()-start;
//---if(end>max_time)
max_time=end;
if(end>100)
{
avr_time+=end;
counter++;
}
}
Print("SymbolInfoTick max bad time: ",DoubleToString(max_time/1000.0,3)," ms; avr bad time: ",counter ? DoubleToString(avr_time/1000.0/counter,3):"0"," ms; bad iterations: ",counter," total iterations: ",count);
}
//+------------------------------------------------------------------+//| |//+------------------------------------------------------------------+void TestPositionSelectByTicket()
{
//---ulong start,end,max_time=0,avr_time=0,counter=0;
int count=100000;
for(int i=0; i<count; i++)
{
start=GetMicrosecondCount();
GetBid();
end=GetMicrosecondCount()-start;
//---if(end>max_time)
max_time=end;
if(end>100)
{
avr_time+=end;
counter++;
}
}
Print("GetBid max bad time: ",DoubleToString(max_time/1000.0,3)," ms; avr bad time: ",counter ? DoubleToString(avr_time/1000.0/counter,3):"0"," ms; bad iterations: ",counter," total iterations: ",count);
}
20 Expert Advisors on EURUSD, i.e. all OnTick processes simultaneously. The build of the terminal is 2664. The test is running without optimization, compilation and other additional load at 100% CPU - you are not going to run a real "hft" trading on this background, are you?
2020.10.2911:10:49.133SymbolInfoTick (EURUSD,M15) GetBid max bad time: 28.004 ms; avr bad time: 0.393 ms; bad iterations: 1569 total iterations: 1000002020.10.2911:10:49.136SymbolInfoTick (EURUSD,H1) GetBid max bad time: 4.795 ms; avr bad time: 0.361 ms; bad iterations: 1783 total iterations: 1000002020.10.2911:10:49.137SymbolInfoTick (EURUSD,M15) GetBid max bad time: 25.367 ms; avr bad time: 0.425 ms; bad iterations: 1496 total iterations: 1000002020.10.2911:10:49.138SymbolInfoTick (EURUSD,M15) GetBid max bad time: 2.681 ms; avr bad time: 0.352 ms; bad iterations: 1804 total iterations: 1000002020.10.2911:10:49.139SymbolInfoTick (EURUSD,M15) GetBid max bad time: 4.264 ms; avr bad time: 0.370 ms; bad iterations: 1734 total iterations: 1000002020.10.2911:10:49.142SymbolInfoTick (EURUSD,H1) GetBid max bad time: 7.049 ms; avr bad time: 0.362 ms; bad iterations: 1803 total iterations: 1000002020.10.2911:10:49.142SymbolInfoTick (EURUSD,M15) GetBid max bad time: 13.376 ms; avr bad time: 0.365 ms; bad iterations: 1754 total iterations: 1000002020.10.2911:10:49.144SymbolInfoTick (EURUSD,H1) GetBid max bad time: 18.048 ms; avr bad time: 0.417 ms; bad iterations: 1516 total iterations: 1000002020.10.2911:10:49.144SymbolInfoTick (EURUSD,M15) GetBid max bad time: 21.280 ms; avr bad time: 0.372 ms; bad iterations: 1769 total iterations: 1000002020.10.2911:10:53.837SymbolInfoTick (EURUSD,M15) SymbolInfoTick max bad time: 0.631 ms; avr bad time: 0.143 ms; bad iterations: 205 total iterations: 1000002020.10.2911:10:53.837SymbolInfoTick (EURUSD,M15) SymbolInfoTick max bad time: 0.517 ms; avr bad time: 0.134 ms; bad iterations: 170 total iterations: 1000002020.10.2911:10:53.837SymbolInfoTick (EURUSD,M15) SymbolInfoTick max bad time: 0.483 ms; avr bad time: 0.144 ms; bad iterations: 178 total iterations: 1000002020.10.2911:10:53.838SymbolInfoTick (EURUSD,M15) SymbolInfoTick max bad time: 0.517 ms; avr bad time: 0.147 ms; bad iterations: 182 total iterations: 1000002020.10.2911:10:53.844SymbolInfoTick (EURUSD,H1) SymbolInfoTick max bad time: 0.582 ms; avr bad time: 0.134 ms; bad iterations: 165 total iterations: 1000002020.10.2911:10:53.845SymbolInfoTick (EURUSD,H1) SymbolInfoTick max bad time: 0.518 ms; avr bad time: 0.137 ms; bad iterations: 195 total iterations: 1000002020.10.2911:10:53.845SymbolInfoTick (EURUSD,M15) SymbolInfoTick max bad time: 0.530 ms; avr bad time: 0.139 ms; bad iterations: 160 total iterations: 1000002020.10.2911:10:53.846SymbolInfoTick (EURUSD,M15) SymbolInfoTick max bad time: 0.575 ms; avr bad time: 0.138 ms; bad iterations: 143 total iterations: 1000002020.10.2911:10:53.848SymbolInfoTick (EURUSD,M15) SymbolInfoTick max bad time: 0.593 ms; avr bad time: 0.143 ms; bad iterations: 206 total iterations: 1000002020.10.2911:10:53.849SymbolInfoTick (EURUSD,M15) SymbolInfoTick max bad time: 0.446 ms; avr bad time: 0.138 ms; bad iterations: 147 total iterations: 1000002020.10.2911:10:53.850SymbolInfoTick (EURUSD,M15) SymbolInfoTick max bad time: 0.661 ms; avr bad time: 0.146 ms; bad iterations: 191 total iterations: 1000002020.10.2911:10:53.850SymbolInfoTick (EURUSD,H1) SymbolInfoTick max bad time: 0.471 ms; avr bad time: 0.141 ms; bad iterations: 219 total iterations: 1000002020.10.2911:10:53.851SymbolInfoTick (EURUSD,M15) SymbolInfoTick max bad time: 0.442 ms; avr bad time: 0.137 ms; bad iterations: 198 total iterations: 1000002020.10.2911:10:53.851SymbolInfoTick (EURUSD,M15) SymbolInfoTick max bad time: 0.574 ms; avr bad time: 0.140 ms; bad iterations: 215 total iterations: 1000002020.10.2911:10:53.853SymbolInfoTick (EURUSD,H1) SymbolInfoTick max bad time: 0.507 ms; avr bad time: 0.140 ms; bad iterations: 222 total iterations: 1000002020.10.2911:10:53.857SymbolInfoTick (EURUSD,H1) SymbolInfoTick max bad time: 0.776 ms; avr bad time: 0.165 ms; bad iterations: 341 total iterations: 1000002020.10.2911:10:53.858SymbolInfoTick (EURUSD,M15) SymbolInfoTick max bad time: 0.568 ms; avr bad time: 0.156 ms; bad iterations: 381 total iterations: 1000002020.10.2911:10:53.860SymbolInfoTick (EURUSD,M15) SymbolInfoTick max bad time: 0.896 ms; avr bad time: 0.164 ms; bad iterations: 293 total iterations: 1000002020.10.2911:10:53.861SymbolInfoTick (EURUSD,M15) SymbolInfoTick max bad time: 6.124 ms; avr bad time: 0.178 ms; bad iterations: 219 total iterations: 1000002020.10.2911:10:53.862SymbolInfoTick (EURUSD,M15) SymbolInfoTick max bad time: 0.794 ms; avr bad time: 0.164 ms; bad iterations: 356 total iterations: 1000002020.10.2911:10:54.686SymbolInfoTick (EURUSD,M15) GetBid max bad time: 4.870 ms; avr bad time: 0.339 ms; bad iterations: 1575 total iterations: 1000002020.10.2911:10:54.728SymbolInfoTick (EURUSD,M15) GetBid max bad time: 6.442 ms; avr bad time: 0.343 ms; bad iterations: 1691 total iterations: 1000002020.10.2911:10:54.732SymbolInfoTick (EURUSD,M15) GetBid max bad time: 7.568 ms; avr bad time: 0.349 ms; bad iterations: 1671 total iterations: 1000002020.10.2911:10:54.755SymbolInfoTick (EURUSD,M15) GetBid max bad time: 13.354 ms; avr bad time: 0.365 ms; bad iterations: 1634 total iterations: 1000002020.10.2911:10:54.773SymbolInfoTick (EURUSD,M15) GetBid max bad time: 9.385 ms; avr bad time: 0.352 ms; bad iterations: 1734 total iterations: 1000002020.10.2911:10:54.778SymbolInfoTick (EURUSD,M15) GetBid max bad time: 2.526 ms; avr bad time: 0.342 ms; bad iterations: 1748 total iterations: 1000002020.10.2911:10:54.785SymbolInfoTick (EURUSD,M15) GetBid max bad time: 15.195 ms; avr bad time: 0.356 ms; bad iterations: 1708 total iterations: 1000002020.10.2911:10:54.790SymbolInfoTick (EURUSD,H1) GetBid max bad time: 5.180 ms; avr bad time: 0.347 ms; bad iterations: 1796 total iterations: 100000
20 EAs on EURUSD, i.e. all OnTick processes at the same time. Terminal build 2664. The test is running without optimization, compilation and other additional workload on 100% CPU - you are not going to run a real "hft" trading on this background, are you?
Typical test log:
You create hothouse conditions by doing 100K iterations for 1.5 seconds on the same tick. I, on the other hand, purposely waited for ticks that didn't generate an OnTick.
Looking through my trade logs, I notice the SymbolInfoTick execution within a few milliseconds. And I know for 100% that the CPU was at full Idle at that time.
It's very simple. There are conditionally 1 million ticks per day. Even 0.01% of ticks slowdown is 100 ticks per day with lags. You'll say that's nonsense. I'll say it's bad. If I run into a lag when I need to make an order, it's a potential monetary loss.
Very grateful that this branch doesn't go unnoticed, and on this feature in particular, a lot of work has been done to speed things up. However, it was a bit of a surprise to me that the awful crutch could outperform the regular function in certain situations. And perhaps if you sorted it out and eliminated that lag, 100 potential lags per day would turn into 10.
I say it's much better than it was at the beginning of the thread. But the fact remains that there are times when it's not good. And I can see that you don't want to look into it. I respect your choice.
Above cited the snapshot option of getting current prices. It would suit me completely if it didn't catch millisecond lags on the Idle-CPU machine.
I'm also worried not only about SymbolInfoTick's speed, but also about the relevance of the prices it returns. I see that you don't raise this question. Apparently you decided to look at it later.
You create hothouse conditions by doing 100K iterations within 1.5 seconds on the same tick. I, on the other hand, specifically waited for ticks that didn't spawn OnTick.
When reviewing my trade logs, I notice that SymbolInfoTick is running for a few milliseconds. I know 100% that the CPU was full Idle at that moment.
It's very simple. In a day there are conditionally 1 million ticks. Even a 0.01% lag is 100 ticks per day with lags. You'll say that's nonsense. I'll say it's bad. If I run into a lag when I need to make an order, it's a potential monetary loss.
Very grateful that this branch doesn't go unnoticed, and on this feature in particular, a lot of work has been done to speed things up. However, it was a bit of a surprise to me that the awful crutch could outperform the regular function in certain situations. And perhaps if you sorted it out and eliminated that lag, 100 potential lags per day would turn into 10.
I say it's much better than it was at the beginning of the thread. But the fact remains that there are times when it's not good. And I can see that you don't want to look into it. I respect your choice.
Above cited the snapshot option of getting current prices. It would suit me completely if it didn't catch millisecond lags on the Idle-CPU machine.
I'm also worried not only about SymbolInfoTick's speed, but also about the relevance of the prices it returns. I see that you don't raise this question. Apparently you decided to look at it later.
These are not warm conditions at all. A loop for 100000 price requests without Sleep() and the like and in 20 threads simultaneously is an obvious stress test. Nothing like that should be even close in real conditions.
If you think there are no other ticks coming in 1.5 seconds - ok, make 10 million queries, it won't change anything, your "crutch" works worse:
NG 010:26:22.903SymbolInfoTick (EURUSD,M15) SymbolInfoTick max bad time: 2.223 ms; avr bad time: 0.146 ms; bad iterations: 22369 total iterations: 10000000
OK 010:26:22.934SymbolInfoTick (EURUSD,M15) SymbolInfoTick max bad time: 1.759 ms; avr bad time: 0.144 ms; bad iterations: 22462 total iterations: 10000000
KO 010:26:22.944SymbolInfoTick (EURUSD,M15) SymbolInfoTick max bad time: 4.587 ms; avr bad time: 0.145 ms; bad iterations: 22620 total iterations: 10000000
RS 010:26:23.443SymbolInfoTick (EURUSD,M15) SymbolInfoTick max bad time: 8.433 ms; avr bad time: 0.162 ms; bad iterations: 36242 total iterations: 10000000
LG 010:26:23.487SymbolInfoTick (EURUSD,M15) SymbolInfoTick max bad time: 9.660 ms; avr bad time: 0.163 ms; bad iterations: 36378 total iterations: 10000000
KH 010:26:23.492SymbolInfoTick (EURUSD,H1) SymbolInfoTick max bad time: 8.433 ms; avr bad time: 0.163 ms; bad iterations: 36208 total iterations: 10000000
HK 010:26:23.505SymbolInfoTick (EURUSD,M15) SymbolInfoTick max bad time: 14.355 ms; avr bad time: 0.164 ms; bad iterations: 36292 total iterations: 10000000
QN 010:27:26.728SymbolInfoTick (EURUSD,M15) GetBid max bad time: 18.589 ms; avr bad time: 0.373 ms; bad iterations: 122026 total iterations: 10000000
HQ 010:27:27.042SymbolInfoTick (EURUSD,H1) GetBid max bad time: 15.544 ms; avr bad time: 0.371 ms; bad iterations: 123026 total iterations: 10000000
RD 010:27:29.190SymbolInfoTick (EURUSD,H1) GetBid max bad time: 16.207 ms; avr bad time: 0.370 ms; bad iterations: 127228 total iterations: 10000000
QJ 010:27:32.661SymbolInfoTick (EURUSD,M15) SymbolInfoTick max bad time: 7.465 ms; avr bad time: 0.495 ms; bad iterations: 994 total iterations: 10000000
CL 010:27:32.799SymbolInfoTick (EURUSD,H1) SymbolInfoTick max bad time: 16.999 ms; avr bad time: 0.585 ms; bad iterations: 1081 total iterations: 10000000
EP 010:27:33.056SymbolInfoTick (EURUSD,H1) SymbolInfoTick max bad time: 11.774 ms; avr bad time: 0.515 ms; bad iterations: 1122 total iterations: 10000000
EE 010:27:33.555SymbolInfoTick (EURUSD,M15) GetBid max bad time: 17.385 ms; avr bad time: 0.368 ms; bad iterations: 134761 total iterations: 10000000
FG 010:27:35.581SymbolInfoTick (EURUSD,M15) SymbolInfoTick max bad time: 10.428 ms; avr bad time: 0.502 ms; bad iterations: 373 total iterations: 10000000
CJ 010:27:46.372SymbolInfoTick (EURUSD,M15) GetBid max bad time: 14.278 ms; avr bad time: 0.360 ms; bad iterations: 153668 total iterations: 10000000
QO 010:27:46.819SymbolInfoTick (EURUSD,M15) GetBid max bad time: 12.494 ms; avr bad time: 0.361 ms; bad iterations: 154170 total iterations: 10000000
KP 010:27:46.897SymbolInfoTick (EURUSD,M15) GetBid max bad time: 17.176 ms; avr bad time: 0.362 ms; bad iterations: 154258 total iterations: 10000000
PE 010:27:47.560SymbolInfoTick (EURUSD,M15) GetBid max bad time: 14.090 ms; avr bad time: 0.362 ms; bad iterations: 156325 total iterations: 10000000
LF 010:27:47.946SymbolInfoTick (EURUSD,M15) GetBid max bad time: 16.794 ms; avr bad time: 0.367 ms; bad iterations: 160557 total iterations: 10000000
IH 010:27:47.970SymbolInfoTick (EURUSD,H1) GetBid max bad time: 11.241 ms; avr bad time: 0.366 ms; bad iterations: 160307 total iterations: 10000000
KN 010:27:51.026SymbolInfoTick (EURUSD,M15) SymbolInfoTick max bad time: 4.961 ms; avr bad time: 0.333 ms; bad iterations: 687 total iterations: 10000000
FP 010:27:51.517SymbolInfoTick (EURUSD,M15) GetBid max bad time: 19.844 ms; avr bad time: 0.372 ms; bad iterations: 165266 total iterations: 10000000
LE 010:27:51.574SymbolInfoTick (EURUSD,M15) GetBid max bad time: 15.435 ms; avr bad time: 0.371 ms; bad iterations: 165785 total iterations: 10000000
QE 010:27:51.686SymbolInfoTick (EURUSD,H1) GetBid max bad time: 13.601 ms; avr bad time: 0.371 ms; bad iterations: 166278 total iterations: 10000000
CK 010:27:52.204SymbolInfoTick (EURUSD,M15) GetBid max bad time: 15.480 ms; avr bad time: 0.374 ms; bad iterations: 161441 total iterations: 10000000
FL 010:27:52.262SymbolInfoTick (EURUSD,M15) GetBid max bad time: 19.503 ms; avr bad time: 0.374 ms; bad iterations: 161363 total iterations: 10000000
FQ 010:27:52.504SymbolInfoTick (EURUSD,M15) GetBid max bad time: 15.440 ms; avr bad time: 0.375 ms; bad iterations: 161927 total iterations: 10000000
KQ 010:27:52.507SymbolInfoTick (EURUSD,H1) GetBid max bad time: 20.155 ms; avr bad time: 0.375 ms; bad iterations: 161670 total iterations: 10000000
EG 010:27:52.558SymbolInfoTick (EURUSD,M15) GetBid max bad time: 15.634 ms; avr bad time: 0.371 ms; bad iterations: 167511 total iterations: 10000000
OK 010:27:52.751SymbolInfoTick (EURUSD,M15) GetBid max bad time: 14.698 ms; avr bad time: 0.368 ms; bad iterations: 168482 total iterations: 10000000
LL 010:27:53.941SymbolInfoTick (EURUSD,M15) GetBid max bad time: 16.659 ms; avr bad time: 0.364 ms; bad iterations: 171194 total iterations: 10000000
JP 010:27:58.244SymbolInfoTick (EURUSD,M15) SymbolInfoTick max bad time: 12.019 ms; avr bad time: 0.308 ms; bad iterations: 970 total iterations: 10000000
OD 010:27:58.879SymbolInfoTick (EURUSD,M15) SymbolInfoTick max bad time: 7.972 ms; avr bad time: 0.299 ms; bad iterations: 1094 total iterations: 10000000
CE 010:28:06.402SymbolInfoTick (EURUSD,M15) GetBid max bad time: 14.140 ms; avr bad time: 0.342 ms; bad iterations: 56289 total iterations: 10000000
EK 010:28:06.860SymbolInfoTick (EURUSD,H1) GetBid max bad time: 14.013 ms; avr bad time: 0.344 ms; bad iterations: 56008 total iterations: 10000000
QL 010:28:06.922SymbolInfoTick (EURUSD,H1) GetBid max bad time: 11.626 ms; avr bad time: 0.343 ms; bad iterations: 56676 total iterations: 10000000
ER 010:28:07.010SymbolInfoTick (EURUSD,M15) GetBid max bad time: 13.021 ms; avr bad time: 0.340 ms; bad iterations: 51610 total iterations: 10000000
ER 010:28:08.708SymbolInfoTick (EURUSD,M15) GetBid max bad time: 2.970 ms; avr bad time: 0.317 ms; bad iterations: 24083 total iterations: 10000000
This your statement is 100% false:
Просматривая логи своей торговли, замечаю исполнение SymbolInfoTick в течение нескольких миллисекунд. При этом на 100% знаю, что в этот момент был полный Idle CPU.
Just like this previous statement of yours:
Уверен, что могу доказать, что получение текущих цен у Вас реализовано очень медленно. И CPU-нагрузка создает такие тормоза только из-за неправильной реализации Вами самой главной функции в MQL5.
Accessing prices via SymbolInfoTick is now very fast and it's completely decoupled from tick stream processing. You're working with a ready-made price cache, which is updated very sparingly and quickly.
All "0.01% tick rate slowdowns" only show up under stress test conditions, and that's a great result. Under normal conditions, access is guaranteed to be very fast.
If you admit that "a lot of work has been done to speed up" SymbolInfoTick, then you should believe me that the "crutch" of getting prices via PositionSelectByTicket cannot be a better solution.
For one simple reason - the implementation of PositionSelectByTicket is completely identical to the original "slow" implementation of SymbolInfoTick.
As I wrote above, this implementation is not slow in the literal sense of the word, but under heavy CPU load, it has a higher probability of runtime outliers (which is clearly visible in my last test).
The timings here are highly dependent on the system task scheduler running under load, i.e. there can be differences from OS to OS and even from version to version.
And the heavier the load, the more you test the performance of the task scheduler, not the terminal.
That's the end of the SymbolInfoTick performance topic.
If your experts create load on the level of synthetic stress tests, then there is one solution: "the iron must match the tasks".
Dear developers, could you please inform me how MQL_MEMORY_USED is calculated?
I made a calculation of memory that all EA variables occupy.
It is less than 10%. If I understand it correctly, MQL_MEMORY_USED contains the History cache and CopyTicks cache. But it is still much less.
At the same time, the parallel Expert Advisor consumes several times less. But the principle is the same.
In general, what is included to this value?
I have saved a template with Expert Advisor and applied it to the same chart by causing reloading. I have seen it like this.
The memory usage has changed by almost an order of magnitude. So far, it is difficult to explain what it means.
Many programs have cumulative effect of memory usage. This is a sin of browsers and sometimes even Word. The Terminal may also be guilty of it. Besides, all logs are written by default and it's easy to spend a week if you have too many actions in one giga. This is an evil which must be managed. But it is not clear how.
Maybe you know how to programmatically select a financial instrument and not get hung up for ages ?
Through an indicator
Forum on trading, automated trading systems and trading strategy testing
MT5 and Speed in Action
Renat Fatkhullin, 2020.10.14 04:15
For mass ticking put more memory.
4gb (price €20) is no good in 2020 when it comes to analytics and research.
For Market Products this approach is no good anywhere. We have to bypass the 10-second retention of unnecessary data through such a crutch.
Making a trivial Market Product in the form of a Market Screener is actually not an achievable task for MT5 due to excessive memory consumption.
Making a trivial Market product in the form of a Market Screener is actually not an achievable task for the MT5 due to excessive memory consumption.
The terminal eats so much memory after launching.
After execution of the screener it started to eat 2 gigs (TERMINAL_MEMORY_USED and did not decrease with time). This is with only one open chart for 5000 M1-bars.
Did not save a screenshot. But decided to throw in an example, which shows memory eating Terminal not in itself, where it's just stupid.
The script just makes copies of the original symbols from the Market Watch. I was supposed to add all the symbols on MQ-Demo and run this script first time on cold and then again on hot.
And after the hot run (when the ticks are already on SSD in the form of tkc-files) I will observe enormous memory exhaustion where it's not needed in a proper implementation.
However, running the script, I've encountered that it hangs on MQ-Demo. It can be unloaded only through Abnormal termination, after which the Terminal will not release more than 1 GB of memory.
It's easy to compare this screenshot with the one in the beginning.
Sorry, not sure if this is a bug or a feature. I haven't found an answer on my own. But the question is related to performance and I suppose it's better to ask it here.
If I add, for example, 22 buffers of DRAW_SECTION type to an empty indicator, then at startup of such an indicator for one chart containing 1000000 bars or more the terminal lags significantly (it causes significant CPU load) and eats significant amounts of memory, even if the indicator calculates nothing.
My interest was aroused by the fact that if you use buffers with other types, everything works without problems and such slowdown is not observed.
For example, I executed the following code on a single chart with 1000000 bars and it consumed about 500 MBytes and lags, especially the chart itself.
But if I change the buffers type to, say, DRAW_LINE, the load on the processor is reduced dramatically, lags are not observed, and memory consumes 5 times less (about 100 MBytes consumed).
Similar tests were done on different builds, up to 2019 builds and the situation is the same.
An individual citizen pulled outa duplicate of an invaluable load of MQL code from his wide trousers, which showed that under the same conditions the crutch worked faster than the regular function.
A very simple test:
20 Expert Advisors on EURUSD, i.e. all OnTick processes simultaneously. The build of the terminal is 2664. The test is running without optimization, compilation and other additional load at 100% CPU - you are not going to run a real "hft" trading on this background, are you?
Typical test log:
A very simple test:
20 EAs on EURUSD, i.e. all OnTick processes at the same time. Terminal build 2664. The test is running without optimization, compilation and other additional workload on 100% CPU - you are not going to run a real "hft" trading on this background, are you?
Typical test log:
You create hothouse conditions by doing 100K iterations for 1.5 seconds on the same tick. I, on the other hand, purposely waited for ticks that didn't generate an OnTick.
Looking through my trade logs, I notice the SymbolInfoTick execution within a few milliseconds. And I know for 100% that the CPU was at full Idle at that time.
It's very simple. There are conditionally 1 million ticks per day. Even 0.01% of ticks slowdown is 100 ticks per day with lags. You'll say that's nonsense. I'll say it's bad. If I run into a lag when I need to make an order, it's a potential monetary loss.
Very grateful that this branch doesn't go unnoticed, and on this feature in particular, a lot of work has been done to speed things up. However, it was a bit of a surprise to me that the awful crutch could outperform the regular function in certain situations. And perhaps if you sorted it out and eliminated that lag, 100 potential lags per day would turn into 10.
I say it's much better than it was at the beginning of the thread. But the fact remains that there are times when it's not good. And I can see that you don't want to look into it. I respect your choice.
Above cited the snapshot option of getting current prices. It would suit me completely if it didn't catch millisecond lags on the Idle-CPU machine.
I'm also worried not only about SymbolInfoTick's speed, but also about the relevance of the prices it returns. I see that you don't raise this question. Apparently you decided to look at it later.
You create hothouse conditions by doing 100K iterations within 1.5 seconds on the same tick. I, on the other hand, specifically waited for ticks that didn't spawn OnTick.
When reviewing my trade logs, I notice that SymbolInfoTick is running for a few milliseconds. I know 100% that the CPU was full Idle at that moment.It's very simple. In a day there are conditionally 1 million ticks. Even a 0.01% lag is 100 ticks per day with lags. You'll say that's nonsense. I'll say it's bad. If I run into a lag when I need to make an order, it's a potential monetary loss.
Very grateful that this branch doesn't go unnoticed, and on this feature in particular, a lot of work has been done to speed things up. However, it was a bit of a surprise to me that the awful crutch could outperform the regular function in certain situations. And perhaps if you sorted it out and eliminated that lag, 100 potential lags per day would turn into 10.
I say it's much better than it was at the beginning of the thread. But the fact remains that there are times when it's not good. And I can see that you don't want to look into it. I respect your choice.
Above cited the snapshot option of getting current prices. It would suit me completely if it didn't catch millisecond lags on the Idle-CPU machine.
I'm also worried not only about SymbolInfoTick's speed, but also about the relevance of the prices it returns. I see that you don't raise this question. Apparently you decided to look at it later.
These are not warm conditions at all. A loop for 100000 price requests without Sleep() and the like and in 20 threads simultaneously is an obvious stress test. Nothing like that should be even close in real conditions.
If you think there are no other ticks coming in 1.5 seconds - ok, make 10 million queries, it won't change anything, your "crutch" works worse:This your statement is 100% false:
Just like this previous statement of yours:
Accessing prices via SymbolInfoTick is now very fast and it's completely decoupled from tick stream processing. You're working with a ready-made price cache, which is updated very sparingly and quickly.
All "0.01% tick rate slowdowns" only show up under stress test conditions, and that's a great result. Under normal conditions, access is guaranteed to be very fast.
If you admit that "a lot of work has been done to speed up" SymbolInfoTick, then you should believe me that the "crutch" of getting prices via PositionSelectByTicket cannot be a better solution.
For one simple reason - the implementation of PositionSelectByTicket is completely identical to the original "slow" implementation of SymbolInfoTick.
As I wrote above, this implementation is not slow in the literal sense of the word, but under heavy CPU load, it has a higher probability of runtime outliers (which is clearly visible in my last test).
The timings here are highly dependent on the system task scheduler running under load, i.e. there can be differences from OS to OS and even from version to version.
And the heavier the load, the more you test the performance of the task scheduler, not the terminal.
That's the end of the SymbolInfoTick performance topic.
If your experts create load on the level of synthetic stress tests, then there is one solution: "the iron must match the tasks".
I have a question about the relevance of the ticks given by SymbolInfoTick.
Situation:
1. We do TimeCurretn(); we get time 18:00:00
2. Do SymbolInfoTick on an invalid symbol. We get a tick with the time 17:58:00.
3. Sleep(1)
4. Adds a SymbolInfoTick for the non-left symbol. We get a tick with the time 17:59:00.
I.e., in the fourth item we have a new tick, which is one minute different than TimeCurretn().
Do you see a problem in this situation?
How to get into this situation less often ?
I have a question about the relevance of the ticks given by SymbolInfoTick.
Situation:
1. We do TimeCurretn(); we get time 18:00:00
2. Do SymbolInfoTick on an unlabeled symbol. We get a tick with the time 17:58:00.
3. Sleep(1)
4. Adds a SymbolInfoTick for the non-left symbol. We get a tick with the time 17:59:00.
I.e., in the fourth item we have a new tick, which is one minute different than TimeCurretn().
Do you see a problem in this situation?
How to get into this situation less often ?
SymbolInfoTick sends the data received from the broker server. What the server sent is what you get.
If there are questions about the tick stream which is broadcasted by your broker, then you have to contact your broker.