OnTimer() has a very large delay. How to solve it? - page 2

 
Longsen Chen #:

Your code is very good to get accurate timer only if Ontimer() is called expectedly. What if Ontimer() is not called, especially when system is busy and for 24 hours test.

Seems that the reply is easy, if your system is too loaded and the timer do not work as expected, the problem is not the timer itself...
 
Fabio Cavalloni #:
I don't know, I'm using EA and indicators based on fast timers (<1 second) and the refresh is as expected, never had a single problem.

I trusted that OnTimer is scheduled on time before I measure it. I also use 100 ms timer but it's not reliable neither.

 
William Roeder #:

The timer is reliable, but it won't run while it or OnTick is running.
      How To Ask Questions The Smart Way. (2004)
          Don't rush to claim that you have found a bug.
      Questions Not To Ask
          My program doesn't work. I think system facility X is broken.

It is almost always your code.

See my countdown timer (MT4)
          Indicators: Zero Lag Timer - Indices - Articles, Library comments - MQL5 programming forum #8 (2017)

Your countdown codes are good and useful.

Since you calculate the remaining seconds each time when OnTimer() is called, you won't sense if OnTimer() is skipped for several seconds. 

void OnTimer(){
   #define  HR2400   86400 // int(PERIOD_D1 * 60)
   datetime servertime  = TimeLocal() + localToServer;
   int      remaining   = int(Time[0] + PeriodSeconds() - servertime);
   int      seconds     = remaining % HR2400;
   int      days        = (remaining - seconds)/HR2400;
   string   display     = (days > 0 ? string(days)+"-" : "")
                        + TimeToString(remaining, TIME_SECONDS);
   ObjectSetText(TIMER, display, textSize, sFontType, fntcolor);
}
 
Longsen Chen #:

Your countdown codes are good and useful.

Since you calculate the remaining seconds each time when OnTimer() is called, you won't sense if OnTimer() is skipped for several seconds. 

One thing to notice about OnTimer and real time operations.

Windows, Mac and Linux are preemptive multithreaded operating systems, based on a scheduler. They are not (except for Linux, which can be compiled as RT) real time scheduled operating systems.

Back in the late 90s, ISDN cards were very expensive, because they needed a separate processor to handle the critical timings of the ISDN protocol. As computes got more powerful, cheap cards showed up, because the OS was (if not overloaded) fast enough to handle the timings, just by the fact, it was called frequent enough to not miss any messages. That was the rise of the cheap Fritz ISDN adapers.

Windows OS supports timers with nanosecond resolution, but you will find out, it's also not as reliable as you think. MQL timer is "not reliable" because it internally adjusts the calls to give you an average frequency of calls, defined by your request. If your request iE is, depending on your CPU and available resources,below a certain threshold, you will get "unreliable" execution. On my CPU (i7 3770k at 4.6GHz) I can go down to around 20ms before getting unreliable. But only if I am not using the machine to much.

It all is very strong depending on your specific environment and use case.

Example: your OnTimer has different runtimes for each call, you will get execution all over the place, as MT tries to adjust the calls to your requirements, but if they change all the time, it is not possible to estimate your requirements.

On the other hand, if your OnTimer function is most deterministic in it's requirements, you will see a settling of the call frequency.

What I did is try to counter the indeterministic calltimes of my function, filling up the early finishing with Sleep, and continuously counter settling the runtime.

This will work and help the scheduler of MT to manage your call frequencies.

But it will take quite some logic to make it work.

As far as I was able to figure out, the scheduler of MT applies it's adjustments not to the next call, but to the following. So you have always at least 7 calls in which you get irrational call frequencies before you and the MT scheduler can settle in.


 
Dominik Christian Egert #:
One thing to notice about OnTimer and real time operations.

Windows, Mac and Linux are preemptive multithreaded operating systems, based on a scheduler. They are not (except for Linux, which can be compiled as RT) real time scheduled operating systems.

Back in the late 90s, ISDN cards were very expensive, because they needed a separate processor to handle the critical timings of the ISDN protocol. As computes got more powerful, cheap cards showed up, because the OS was (if not overloaded) fast enough to handle the timings, just by the fact, it was called frequent enough to not miss any messages. That was the rise of the cheap Fritz ISDN adapers.

Windows OS supports timers with nanosecond resolution, but you will find out, it's also not as reliable as you think. MQL timer is "not reliable" because it internally adjusts the calls to give you an average frequency of calls, defined by your request. If your request iE is, depending on your CPU and available resources,below a certain threshold, you will get "unreliable" execution. On my CPU (i7 3770k at 4.6GHz) I can go down to around 20ms before getting unreliable. But only if I am not using the machine to much.

It all is very strong depending on your specific environment and use case.

Example: your OnTimer has different runtimes for each call, you will get execution all over the place, as MT tries to adjust the calls to your requirements, but if they change all the time, it is not possible to estimate your requirements.

On the other hand, if your OnTimer function is most deterministic in it's requirements, you will see a settling of the call frequency.

What I did is try to counter the indeterministic calltimes of my function, filling up the early finishing with Sleep, and continuously counter settling the runtime.

This will work and help the scheduler of MT to manage your call frequencies.

But it will take quite some logic to make it work.

As far as I was able to figure out, the scheduler of MT applies it's adjustments not to the next call, but to the following. So you have always at least 7 calls in which you get irrational call frequencies before you and the MT scheduler can settle in.


Thank you very much, Dominik.  Obviously you are very experienced in dealing with accurate timer. I never know MT adjust the calls. In my codes, the OnTimer() is very simple, it should be deterministic in execution time.

I have a question, in my case each MT opened two charts. One chart runs a copy EA and the another is just a simple code measuring the timer dealy. From MQL documentation, each chart has independent thread. Two charts won't interact, right?

Is there any way to get a reliable timer?

 
Longsen Chen #:

I trusted that OnTimer is scheduled on time before I measure it. I also use 100 ms timer but it's not reliable neither.

I have OnTimer in my EA with bunch of functions and the comment chart refreshing information with current time too. 

It always refresh correctly without skipping a single second. If it was like you said, i will see the time not refreshing for something like 800 seconds, which never happened for me...
 
Longsen Chen #:

Thank you very much, Dominik.  Obviously you are very experienced in dealing with accurate timer. I never know MT adjust the calls. In my codes, the OnTimer() is very simple, it should be deterministic in execution time.

I have a question, in my case each MT opened two charts. One chart runs a copy EA and the another is just a simple code measuring the timer dealy. From MQL documentation, each chart has independent thread. Two charts won't interact, right?

Is there any way to get a reliable timer?

The same Symbol shares a thread across the charts. - As far as I know.

What I did to make a most precise timer was to build my own managing function sets.

An outline:

Use OnTimer and find out the lowest reliable call frequency by slowly degrading the call time with SetMillisecondTimer

After a settlement, hook in the payload function, the actual function to be called. Measure the time it takes for it to execute.

After that, add the missing time with a sleep, so that whatever the payload function does, the runtime on OnTimer is always (about) the same.

One thing that I noticed, it helps a lot to have a much higher frequency on OnTimer than on your payload function.

So if you want a call every second, your frequency should be around at least 100ms.

You need to find some tradeoff, because OnTimer blocks OnTick. Since you keep adjusting the runtime, you might even split up the payload function into multiple chunks, so that you can stack the calls in OnTimer to accumulate enough runtime.

It is difficult to manage, because MT keeps interfering with your call times and runtimes.

So I made it in such way, that I flow into a settlement and after around 100 calls to OnTimer, the timing is aligned with the payload runtime and wanted call frequency.

I then decouple the adjustment code, and just use a small millisecond adjustment on each call to compensate for different runtimes. I use microseconds to do so, but stick to milliseconds for adjustment. At this point I do not change the call timer itself anymore, as this introduces drift again.

It's from there on like fxsaber did it in his code.

All I did was find the indeterministic runtimes of the payload and use the 95/5 rule applies to the max value.

You will still have some slight drift, but it's within margin of error and you can adjust for that.
 
Fabio Cavalloni #:
I have OnTimer in my EA with bunch of functions and the comment chart refreshing information with current time too. 

It always refresh correctly without skipping a single second. If it was like you said, i will see the time not refreshing for something like 800 seconds, which never happened for me...

That's good OnTimer() works well in your case. I'm not so lucky unfortunately.

 
Dominik Christian Egert #:
The same Symbol shares a thread across the charts. - As far as I know.

What I did to make a most precise timer was to build my own managing function sets.

An outline:

Use OnTimer and find out the lowest reliable call frequency by slowly degrading the call time with SetMillisecondTimer

After a settlement, hook in the payload function, the actual function to be called. Measure the time it takes for it to execute.

After that, add the missing time with a sleep, so that whatever the payload function does, the runtime on OnTimer is always (about) the same.

One thing that I noticed, it helps a lot to have a much higher frequency on OnTimer than on your payload function.

So if you want a call every second, your frequency should be around at least 100ms.

You need to find some tradeoff, because OnTimer blocks OnTick. Since you keep adjusting the runtime, you might even split up the payload function into multiple chunks, so that you can stack the calls in OnTimer to accumulate enough runtime.

It is difficult to manage, because MT keeps interfering with your call times and runtimes.

So I made it in such way, that I flow into a settlement and after around 100 calls to OnTimer, the timing is aligned with the payload runtime and wanted call frequency.

I then decouple the adjustment code, and just use a small millisecond adjustment on each call to compensate for different runtimes. I use microseconds to do so, but stick to milliseconds for adjustment. At this point I do not change the call timer itself anymore, as this introduces drift again.

It's from there on like fxsaber did it in his code.

All I did was find the indeterministic runtimes of the payload and use the 95/5 rule applies to the max value.

You will still have some slight drift, but it's within margin of error and you can adjust for that.

Thanks again for your outline.

I am using different symbols in two charts.

I understand your idea and method. My real work within OnTimer() includes open trades and close trades. It may take no time in case of no trade or long time to make several orders. It's difficult to manage the execution time for such tasks inside OnTimer();

Anyway, your work is valuable.

 
By the way, I observed that MT5 has less delay than MT4 in the same computer.