Declaring variables behind the loop or inside the loop? - page 2

 
Georgiy Merts:

No, I'm not.

Certainly, a normal compiler in this case should bring a variable declaration inside a loop to the outside.

I just think you should always trust the compiler and trust yourself. It is a compiler standard that a local variable is created when it is declared and is removed when the block in which it was declared is exited. So you should focus on this principle in the first place and not wait for the compiler to improve your code for you.

So I say if you want to "make it better", go to assembler, if you need to control everything yourself... After all, the case you just described is nothing at all. There are much more complicated things. OOP is definitely contraindicated for you. You won't know whether or not the compiler has degenerated a particular virtual method into a regular call, or whether it has cut an unnecessary pointer check... What can you do in a managed MQL with such paranoia? )

And tweaking code to fit the peculiarities of the compiler (and imaginary ones at that), to the detriment of code correctness and reliability, is obviously not what a good programmer should do. And here we are talking exactly about code incorrectness. The variable must be declared directly in the block in which it is used.

 
Vict:

Man, that's just wildly dumb, what's there to comment on, a complete lack of understanding of how the debugger works.

You do.
 
Alexey Navoykov:
You do.

Like in kindergarten ))) I explain for those who are in the tank: first we compile g++ 1.cpp, there are no breakpoints there, compiler doesn't know anything about them. Then run debugger: gdb a.out, and only now put breakpoint.

Do you understand what nonsense you said?

 
Alexey Navoykov:

You can detect optimization only by compiling the code or measuring its performance. That's the first thing you should do. And calm down )

2019.08.18 10:28:12.826 SpeedTest (EURUSD,H1) 1. s1=rand(): loops=100000000 ms=7031

2019.08.18 10:28:19.885 SpeedTest (EURUSD,H1) 2. s2=rand(): loops=100000000 ms=7063

2019.08.18 10:28:27.037 SpeedTest (EURUSD,H1) 3. s3=rand(): loops=100000000 ms=7140

2019.08.18 10:28:34.045 SpeedTest (EURUSD,H1) 4. s4=rand(): loops=100000000 ms=7016

2019.08.18 10:28:41.135 SpeedTest (EURUSD,H1) 5. s5=rand(): loops=100000000 ms=7094

2019.08.18 10:28:47.896 SpeedTest (EURUSD,H1) 1. q=rand(): loops=100000000 ms=6750

2019.08.18 10:28:54.659 SpeedTest (EURUSD,H1) 2. q=rand(): loops=100000000 ms=6765

2019.08.18 10:29:01.447 SpeedTest (EURUSD,H1) 3. q=rand(): loops=100000000 ms=6797

2019.08.18 10:29:08.257 SpeedTest (EURUSD,H1) 4. q=rand(): loops=100000000 ms=6797

2019.08.18 10:29:15.102 SpeedTest (EURUSD,H1) 5. q=rand(): loops=100000000 ms=6844

//+------------------------------------------------------------------+
//|                                                    SpeedTest.mq5 |
//|                                                            IgorM |
//|                              https://www.mql5.com/ru/users/igorm |
//+------------------------------------------------------------------+
#property copyright "IgorM"
#property link      "https://www.mql5.com/ru/users/igorm"
#property version   "1.00"
#define  N 8

#define    test(M,S,EX) {uint mss=GetTickCount();ulong nn=(ulong)pow(10,M);for(ulong tst=0;tst<nn&&!_StopFlag;tst++){EX;} \
                        printf("%s: loops=%i ms=%u",S,nn,GetTickCount()-mss);}
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   string s1; srand(GetTickCount()); test(N,"1. s1=rand()",s1=IntegerToString(rand()));
   string s2; srand(GetTickCount()); test(N,"2. s2=rand()",s2=IntegerToString(rand()));
   string s3; srand(GetTickCount()); test(N,"3. s3=rand()",s3=IntegerToString(rand()));
   string s4; srand(GetTickCount()); test(N,"4. s4=rand()",s4=IntegerToString(rand()));
   string s5; srand(GetTickCount()); test(N,"5. s5=rand()",s5=IntegerToString(rand()));

   srand(GetTickCount()); test(N,"1. q=rand()",string q=IntegerToString(rand()));
   srand(GetTickCount()); test(N,"2. q=rand()",string q=IntegerToString(rand()));
   srand(GetTickCount()); test(N,"3. q=rand()",string q=IntegerToString(rand()));
   srand(GetTickCount()); test(N,"4. q=rand()",string q=IntegerToString(rand()));
   srand(GetTickCount()); test(N,"5. q=rand()",string q=IntegerToString(rand()));
  }
//+------------------------------------------------------------------+
 
I dug under the debugger for similar code, but without user operator new, well, there could be some doubts - the user operator is not optimized. Caught a call of malloc() from libc. The result: string in loop - one call before each print, out of loop - one call before a batch of prints. There can be no doubt about it, only the first variant is better. Of course, it's possible that something is different in µl, but it's better to be guided by mature languages.
 
#define  N 9

2019.08.18 10:37:59.620 SpeedTest (EURUSD,H1) 1. s1=rand(): loops=1000000000 ms=70672

2019.08.18 10:39:10.352 SpeedTest (EURUSD,H1) 2. s2=rand(): loops=1000000000 ms=70719

2019.08.18 10:40:21.908 SpeedTest (EURUSD,H1) 3. s3=rand(): loops=1000000000 ms=71562

2019.08.18 10:41:32.315 SpeedTest (EURUSD,H1) 4. s4=rand(): loops=1000000000 ms=70407

2019.08.18 10:42:42.996 SpeedTest (EURUSD,H1) 5. s5=rand(): loops=1000000000 ms=70687

2019.08.18 10:43:50.964 SpeedTest (EURUSD,H1) 1. q=rand(): loops=1000000000 ms=67969

2019.08.18 10:44:58.887 SpeedTest (EURUSD,H1) 2. q=rand(): loops=1000000000 ms=67922

2019.08.18 10:46:06.829 SpeedTest (EURUSD,H1) 3. q=rand(): loops=1000000000 ms=67937

2019.08.18 10:47:14.602 SpeedTest (EURUSD,H1) 4. q=rand(): loops=1000000000 ms=67766

2019.08.18 10:48:22.428 SpeedTest (EURUSD,H1) 5. q=rand(): loops=1000000000 ms=67828

 

Igor Makanu:

#define    test(M,S,EX) {uint mss=GetTickCount();ulong nn=(ulong)pow(10,M);for(ulong tst=0;tst<nn&&!_StopFlag;tst++){EX;} \

Man, is the "space bar" not working for you? Not the first time I've noticed that. Or are you saving bytes on your hard drive? )

 
Alexey Navoykov:

Are you kidding? It's such a trivial situation for a compiler that there's nothing to talk about. You can't be so paranoid about it and just code in assembler. ) Although even that is becoming senseless nowadays. You will have to try hard to beat optimization of modern compilers.

p.s. Maybe I was a bit excited about triviality here because I'm talking about the string buffer. But it is guaranteed to be saved in MQL, not only inside the loop but even between function calls. This topic was discussed here more than once

I have a suspicion that the author of this statement doesn't know at all how the processor, memory and compiler work... I bet that any of your code can be accelerated at least ten times, or even hundreds times. Because of such shitty coders most products are now unbearably slow on powerful computers with dozens of cores, while you just need to think a little... But some people think: "Why think? You have to code..."

For your information, no compiler at the moment has learned to understand what the programmer wanted to get as a result. It can unroll some loops and optimize some memory accesses to keep data in cache of the processor, but if the code was not optimized to begin with and is written through one place, no compiler can help you...

P.S. Read at your leisure an entertaining book by Chris Kaspersky"Program Optimization Technique. Efficient Memory Usage".

 
Alexey Volchanskiy:

Georges is right, it's not guaranteed.

And we get a warping implicit conversion from 'number' to 'string'


And that's exactly how you get rid of ambiguity and warping.

for (int i = 0; i < 1000; i++)
   {
      static string st = IntegerToString(i);
      ...
   }

That's how I've always done it.

string st = (string)i;

And what's the point of static? The assignment will only work once in the first iteration.


I decided to measure the speed of execution.

   CStopWatch sw; // Секундомер, для замера времени
   
   sw.Start();
   for (int i = 0; i < 10000000; i++)
   {
      string st = (string)i;
   }
   pr("Test1, время выполнения: " + sw.Stop());

   sw.Start();
   string st = "";
   for (int i = 0; i < 10000000; i++)
   {
      st = (string)i;
   }
   pr("Test2, Время выполнения: " + sw.Stop());

The result:

Test1, время выполнения: 0.548275 сек.
Test2, Время выполнения: 0.313978 сек.

Ran it many times, the result is stable, the code with the declaration of a variable after the loop, works faster

 
Alexey Navoykov:

Man, is the "space bar" not working for you? Not the first time I've noticed that. Or are you saving bytes on your hard drive? )

No, this code is not mine, I refined it a little - I copied the code for myself from the thread about "search for semi-colons" and use it for controversial questions, I'm too lazy to change it,

I have spaces and I'm too lazy to do it ))))

ZS: give me a model code, I'll copy it to myself, it will be as you want in the future, I'm in principle, it does not bother me

ZS: here AD :

#define    test(M,S,EX) {                                 \
uint mss=GetTickCount();                                 \
ulong nn=(ulong)pow(10,M);                               \
for(ulong tst=0;tst<nn && !_StopFlag;tst++) \
{ EX; }                                                  \
printf("%s: loops=%i ms=%u",S,nn,GetTickCount()-mss);}