Объявление переменных за циклом или внутри цикла? - страница 4

 

Прошу прощения народ, оптимизация была выключена в настройках проекта

Код:

   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());


Без оптимизации

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

С оптимизацией

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

С оптимизацией да, все наоборот, проверил много раз

 
Aleksandr Matveev:

Хватит уже флудить, матчасть сначала освойте, а потом уже доказывайте свою правоту. Вам результат был бы понятен без каких-либо тестов, если бы вы как минимум прочитали хоть одну книжку по работе процессора и памяти. Я вам предложил самую гениальную из них, если вы захотите немого продвинутся в программировании, то вы ее обязательно прочитаете.

Причем тут память и процессор, речь про оптимизацию, теоретик вы книжный)

 
Igor Makanu:

не странно, нужно уметь тестировать простейшие операторы и операции в MQL - ну вот на  кой я я добавил в свой тест srand(GetTickCount()) ?

;)

Кстати посмотрел внимательнее, у вас же там тоже результат в цикле никак не учитывается в дальнейшем, а значит компилятор его может легко вырезать.

 
Alexey Navoykov:

Кстати посмотрел внимательнее, у вас же там результат в цикле никак не учитывается в дальнейшем, а значит компилятор его может легко вырезать.

убрал даже rand() - его компилятор прекрасно инлайнит, сделал такой тест:

#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;  test(N,"1. s1=rand()",s1=(string)tst);
   string s2;  test(N,"2. s2=rand()",s2=(string)tst);
   string s3;  test(N,"3. s3=rand()",s3=(string)tst);
   string s4;  test(N,"4. s4=rand()",s4=(string)tst);
   string s5;  test(N,"5. s5=rand()",s5=(string)tst);

   test(N,"1. q=rand()",string q=(string)tst);
   test(N,"2. q=rand()",string q=(string)tst);
   test(N,"3. q=rand()",string q=(string)tst);
   test(N,"4. q=rand()",string q=(string)tst);
   test(N,"5. q=rand()",string q=(string)tst);
  }
//+------------------------------------------------------------------+

2019.08.18 11:55:41.457 SpeedTest (EURUSD,H1) 1. s1=rand(): loops=100000000 ms=7672

2019.08.18 11:55:49.085 SpeedTest (EURUSD,H1) 2. s2=rand(): loops=100000000 ms=7625

2019.08.18 11:55:56.796 SpeedTest (EURUSD,H1) 3. s3=rand(): loops=100000000 ms=7719

2019.08.18 11:56:04.495 SpeedTest (EURUSD,H1) 4. s4=rand(): loops=100000000 ms=7703

2019.08.18 11:56:12.113 SpeedTest (EURUSD,H1) 5. s5=rand(): loops=100000000 ms=7610

2019.08.18 11:56:17.695 SpeedTest (EURUSD,H1) 1. q=rand(): loops=100000000 ms=5578

2019.08.18 11:56:23.362 SpeedTest (EURUSD,H1) 2. q=rand(): loops=100000000 ms=5672

2019.08.18 11:56:28.970 SpeedTest (EURUSD,H1) 3. q=rand(): loops=100000000 ms=5609

2019.08.18 11:56:34.637 SpeedTest (EURUSD,H1) 4. q=rand(): loops=100000000 ms=5672

2019.08.18 11:56:40.277 SpeedTest (EURUSD,H1) 5. q=rand(): loops=100000000 ms=5640


 
Alexey Navoykov:

Так вот я и говорю, если хотите "не плошать", то вперёд на ассемблер.  Раз вам нужно самому всё лично контролировать... Ведь описанный случай - это совершенный пустяк. Встречаются вещи на порядки сложнее.  ООП вам точно противопоказано. Вы ж не узнаете, выродил ли компилятор тот или иной виртуальный метод в обычный вызов, или вырезал ли излишнюю проверку указателя...  Что вообще можно делать на управляемом MQL с такой паранойей ? )

Да и подстраивать код под особенности компилятора (причём мнимые), в ущерб правильности и надёжности кода - это явно не то, чем должен заниматься хороший программист.  А здесь речь идёт именно о неправильности кода.  Переменная должна объявляться непосредственно в том блоке, в котором используется.

Ха-ха-ха... Алексей, ты утверждаешь (давай на "ты"), что "ООП точно противопоказан" одному из главному адептов ООП на форуме.

Код надо подстраивать не под особенности компилятора, а под особенности СВОЕГО мышления. В данном случае - объявление переменной внутри цикла в теории снижает эффективность. Потому, что согласно принятым соглашениям - переменная должна создаваться каждый раз, и каждый раз должна уничтожаться.

Тут даже дело не в эффективности. Надежный код - это код, который прозрачен, понятен, и легок для модификации и поддержки.

Лично мне крайне не нравится, когда ворох переменных разбросан по программе, и каждый раз надо искать, где создается та или иная переменная. Поэтому переменные я стараюсь по возможности объявлять вначале функции, все вместе - именно для того, чтобы видеть, где они созданы, и понимать, когда они будут удалены.

В данном случае пример просто очень короткий. Когда там между созданием переменной и ее использованием десятки строк и куча вложенных функций - по мне - гораздо надежнее, когда переменная объявляется снаружи блока, заранее.

 
pivalexander:

Прошу прощения народ, оптимизация была выключена в настройках проекта

Код:


Без оптимизации

С оптимизацией

С оптимизацией да, все наоборот, проверил много раз

У вас вообще в этом примере с помощью оптимизации все тело цикла могло быть вырезано.

 

В общем всё сходится к тому, как и ожидалось, что незачем заниматься ерундой, выискивая себе несуществующие проблемы на ровном месте и создавая реальные.

Если чешутся руки и считаешь себя крутым кулхацкером, то пиши сразу на ассемблере.  Иначе отойди в сторонку и не мешай дяде компилятору делать свою работу )

 
Aleksandr Matveev:

У вас вообще в этом примере с помощью оптимизации все тело цикла могло быть вырезано.

Результат выполнения с пустым телом цикла, сильно отличается, гораздо быстрее работает

Без оптимизации:
Test1, время выполнения: 0.027539 сек.

С оптимизацией:
Test1, время выполнения: 0.005448 сек.
 
Alexey Navoykov:

В общем всё сходится к тому, как и ожидалось, что незачем заниматься ерундой, выискивая себе несуществующие проблемы на ровном месте и создавая реальные.

Если чешутся руки и считаешь себя крутым кулхацкером, то пиши сразу на ассемблере.  Иначе отойди в сторонку и не мешай дяде компилятору делать свою работу )

Главная проблема как раз в том, что я не считаю себя кулхацкером. Именно поэтому переменные, на мой взгляд, следует объявлять снаружи цикла. И лучше - в самом начале функции, сразу все.

А как раз кулхацкеры - могут объявлять переменные по мере надобности, внутри кода.

 
Georgiy Merts:

Главная проблема как раз в том, что я не считаю себя кулхацкером. Именно поэтому переменные, на мой взгляд, следует объявлять снаружи цикла. И лучше - в самом начале функции, сразу все.

А как раз кулхацкеры - могут объявлять переменные по мере надобности, внутри кода.

Предпочитаю разбивать код на логические блоки и объявлять нужные для них переменные в них, а не городить кучу всяких переменных в начале функции, большая часть из которых нужна только в одном блоке, где то там далеко внизу

Причина обращения: