Особенности языка mql5, тонкости и приёмы работы - страница 248

 
trader6_1 #:

А такой вариант?

Выход за пределы массива. Либо, если в Amount уже учтён (размер - 1), то никакой разницы быть не должно от этого: for (int i = Amount - 1; i >= 0; i--)

 
trader6_1 #:

А такой вариант?

Вставьте свой вариант сюда и сравните.

 

Статическая переменная, объявленная внутри метода класса, является статической переменной самого класса.

class A {
   void foo() {
      static int i;
      i++;
      Print(i);
   }
 public:
   A(){foo();};
} o1, o2, o3;

void OnStart() {
}

результат 
1

2

3

Не то, чтобы особенность. Проверил, на С++ так же. И вроде как бы логично все. Но я лично этого не знал. Поэтому по привычке в методах класса часто использовал статические переменные, делая трудноуловимые ошибки(когда объектов класса несколько).

 
Nikolai Semko #:

Статическая переменная, объявленная внутри метода класса, является статической переменной самого класса.

Использую для скорости, чтобы не выделять память на каждом вызове.
  virtual void MultiTick( void )
  {
    static MqlTick Tick = {};

    if (::SymbolInfoTick(this.SymbolOrders, Tick))
      this.NewTick(Tick);

    return;
  }
Не замерял, правда. Возможно, самообман.
 
fxsaber #:
Использую для скорости, чтобы не выделять память на каждом вызове. Не замерял, правда. Возможно, самообман.

Думаю, оправдано. Но, да интересно бы замерить. Вдруг доступ к глобальной переменной происходит дольше, чем выделение новой памяти.

 
Nikolai Semko #:

Думаю, оправдано. Но, да интересно бы замерить. Вдруг доступ к глобальной переменной происходит дольше, чем выделение новой памяти.

Тут от многих факторов зависеть будет.

  1. Вероятность нахождения стека в кэше процессора выше, чем сегментов .data и .bss, просто, исходя из того, что со стеком постоянно операции происходят. 
  2. Если структура, выделяемая на стеке, не великая или используются только отдельные поля, то при оптимизациях, компилятор вообще память на стеке не выделяет, а обходится регистрами.

 Отсюда вывод: не используйте static вместо local storage в вышеприведенном контексте, лучше точно не будет, а вот хуже - почти наверняка.

PS. если в том примере убрать static, то еще надо и инициализацию структуры убрать, что бы процессорное время нее не тратить, она в SymbolInfoTick будет инициализирована.

 
Vladimir Simakov #:

Тут от многих факторов зависеть будет.

  1. Вероятность нахождения стека в кэше процессора выше, чем сегментов .data и .bss, просто, исходя из того, что со стеком постоянно операции происходят. 
  2. Если структура, выделяемая на стеке, не великая или используются только отдельные поля, то при оптимизациях, компилятор вообще память на стеке не выделяет, а обходится регистрами.

 Отсюда вывод: не используйте static вместо local storage в вышеприведенном контексте, лучше точно не будет, а вот хуже - почти наверняка.

PS. если в том примере убрать static, то еще надо и инициализацию структуры убрать, что бы процессорное время нее не тратить, она в SymbolInfoTick будет инициализирована.

Вполне допускаю. 
Все же надо замерить
Только сложно будет сделать объективный замер
 
Nikolai Semko #:
Я это вполне допускаю.
Тем не менее, мы должны его измерить.
Но будет трудно сделать объективное измерение.
Я бы сказал, что это очевидно, потому что стек нужно выделять в любом случае, а значит, это будет сделано за один вызов.

Кроме того, это обеспечит локальность кэша, а также уменьшит подкачку памяти.

Так что преимущества очевидны, имхо.
 
Vladimir Simakov #:

Это зависит от многих факторов.

  1. Стек с большей вероятностью окажется в кэше процессора, чем сегменты .data и .bss, просто исходя из того, что со стеком постоянно происходят операции.
  2. Если структура, выделяемая на стеке, невелика или используются только отдельные поля, то при оптимизации компилятор вообще не выделяет память на стек, а обходится регистрами.

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

PS. Если вы уберете static в этом примере, то уберете и инициализацию структуры, чтобы не тратить процессорное время, она будет инициализироваться в SymbolInfoTick.

Откуда вы знаете, что она будет инициализирована? Разве она не будет просто заполнена значениями? Или вы подразумеваете это под словом "инициализируется".
 
Nikolai Semko #:
Все же надо замерить
Только сложно будет сделать объективный замер

Попробовал.

#define BENCH(A)                                                             \
  {                                                                          \
    const ulong StartTime = GetMicrosecondCount();                           \
    A;                                                                       \
    Print(#A + ":" + (string)(GetMicrosecondCount() - StartTime) + " mcs."); \
  } 

datetime f1( datetime &Tmp )
{
  static MqlTick Tick = {};

  if (!Tmp)
    Tick.time = 1;
    
  return(Tick.time);
}

datetime f2( datetime &Tmp )
{
  MqlTick Tick;

  if (!Tmp)
    Tick.time = 1;
    
  return(Tick.time);
}

void Bench1( datetime &Tmp )
{
  for (int i = 0; i < 1e7; i++)
    Tmp += f1(Tmp);
}

void Bench2( datetime &Tmp )
{
  for (int i = 0; i < 1e7; i++)
    Tmp += f2(Tmp);
}

void OnStart()
{  
  datetime Tmp = 1;

  BENCH(Bench1(Tmp))
  BENCH(Bench2(Tmp))
  
  Print(Tmp);  
}


Результат.

Bench1(Tmp):5675 mcs.
Bench2(Tmp):0 mcs.

Честно говоря, не понимаю, почему во второй строке получается ноль при отсутствии инициализации.

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