Ошибки, баги, вопросы - страница 2667

 
Значит мной описанный баг не интересен разработчикам, ну ладно...
 
Баг МТ5 (build 2345) долго не мог понять почему профайлер запускается, отрабатывает, но результаты ни где не отображаются.
Оказывается, профайлер для проекта скрипта отображает результат только в случаи выключенной оптимизации, если оптимизация включена - все запустится, отработает, но без какого-либо результата.
 
Sergey Dzyublik:
Баг МТ5 (build 2345) долго не мог понять почему профайлер запускается, отрабатывает, но результаты ни где не отображаются.
Оказывается, профайлер для проекта скрипта отображает результат только в случаи выключенной оптимизации, если оптимизация включена - все запустится, отработает, но без какого-либо результата.

Профайлер отрабатывает не для всех индикаторов (без оптимизации). Дважды написал об этом на форуме, скинул в ЛС разработчикам код - нет ответа.

 
Поработал с профайлером в МТ5 (build 2345),
грубо говоря, интересовало почему два алгоритма, дающих в конечном итоге один и тот же результат, выполняются с разной скоростью, просадка в 1.7 раза в режиме оптимизации.

#include <stl_vector.mqh>

// TickCounts: 850
vector<int>::move test_vector_move_return_assign_by_index(int n){
   vector<int> v(n);
   for(int i = 0; i < n; i++){
      v[i].UNREF  = i;
   }
   return v;
};

// TickCounts: 1450
vector<int>::move test_vector_move_return_push_back(int n){
   vector<int> v;
   // lazy implementation  
   v.reserve(n);                      
   for(int i = 0; i < n; i++){
      v.push_back(i);
   }
   return v;
};


void OnStart()
{
   for(int i = 0; i < 20000; i++){
       vector<int> v_int_move = test_vector_move_return_assign_by_index(1000);
   }
   
   for(int i = 0; i < 20000; i++){
      vector<int> v_int_move = test_vector_move_return_push_back(1000);
   }
}


В результате был получен практический опыт работы с профайлером МТ5 и обнаружено ряд дефектов в его работе.
Так как не понятно, интересует ли разработчиков эта информация, а тратить часы собственно времени для локализации багов ни какого желания нет, то будет предоставлена лишь краткая информация по обнаруженным проблемам:

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

2) Некорректное значение Count в сплывающих подсказках гистограмм на экране.
Профайлер пишет, что функция запускалась 80К раз, а не 20К как ожидалось, аналогично внутри функции для разных строк идет превышение Count в разы, для одних строк в три раза, для других в два.

3) Некорректное значение Time в сплывающих подсказках гистограмм на экране.
Имеются случаи, когда профайлер показывает, что алгоритм заходил в условие 99.90% раз по времени, а в действительности оказывается, что только один раз из 20К проходов.

 

Это скорее не баг, а замечание! 


мт 5 билд 2340.

Вчера открыв Каталог данных не заметил как папка Indicators переместилась в папку Experts. Потом выключил мт5 и уже сегодня включил, индикаторы также можно использовать из Навигатора, как ни в чем не бывало. Но, если обратно открыть Каталог данных то там появится пустая папка Indicators и если уже в нее кинуть какой-то индикатор. То он уже не появится в Навигаторе. Возврат папки Indicators обратно в MQL5\Indicators решает проблему. 

 

МТ5 (build 2347) Почему такой большой overhead при добавлении по одному элементу в массив с помощью ArrayResize, если память для них была заранее зарезервирована?

#define K 1000
#define M (1000 * K)

#define   SpeedTest(test_count,msg,EX)        {uint mss=GetTickCount(); ulong count=test_count;for(ulong ii=0;ii<count&&!_StopFlag;ii++){EX;} \
                                              printf("%-60s: loops=%i ms=%u",msg,count,GetTickCount()-mss);}
                                              
class A{
public:
   int data;
};

struct B{
   int data;
};

template<typename T>
void test1(const int test_count, const int array_size){
   SpeedTest(
   test_count,"Test Class ArrayResize all",
   {
      T class_array[];
      for(int i = 1; i <= array_size; i++){
         ArrayResize(class_array, array_size);
      }
   }
   )
};

template<typename T>
void test2(const int test_count, const int array_size){
   SpeedTest(
   test_count,"Test Class ArrayResize one by one with reserved memory",
   {
      T class_array[];
      ArrayResize(class_array, 1, array_size - 1);
      for(int i = 2; i <= array_size; i++){
         ArrayResize(class_array, i);
      }
   }
   )
};

void OnStart()
{
  const int test_count = 5*K;
  const int array_size = 5*K;  
  
  test1<int>(test_count, array_size);            // Avg time: 100
  test2<int>(test_count, array_size);            // Avg time: 190
  test1<int>(test_count, array_size);
  test2<int>(test_count, array_size);
  test1<int>(test_count, array_size);
  test2<int>(test_count, array_size);
  test1<int>(test_count, array_size);
  test2<int>(test_count, array_size);
  
printf("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
  test1<A>(test_count, array_size);              // Avg time: 810
  test2<A>(test_count, array_size);              // Avg time: 1460
  test1<A>(test_count, array_size);
  test2<A>(test_count, array_size);
  test1<A>(test_count, array_size);
  test2<A>(test_count, array_size);
  test1<A>(test_count, array_size);
  test2<A>(test_count, array_size);
  
printf("BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB");
  test1<B>(test_count, array_size);              // Avg time: 110
  test2<B>(test_count, array_size);              // Avg time: 770
  test1<B>(test_count, array_size);
  test2<B>(test_count, array_size);
  test1<B>(test_count, array_size);
  test2<B>(test_count, array_size);
  test1<B>(test_count, array_size);
  test2<B>(test_count, array_size);
}

Прошу рассмотреть возможность улучшения внутреннего алгоритма резервирования с помощью ArrayResize.

Например, для классов можно припустить, что они кроме вызова конструктора выполняют некую "внутреннюю регистрацию в списках".
И в рамках резервирования с помощью ArrayResize, кроме непосредственного выделения памяти, можно попробовать оптимизировать процесс:
- брать данные из соседнего созданного элемента (например указатель на таблицу виртуальных функций);
- заранее выполнять или резервировать место под "внутреннюю регистрацию" классов, которые еще не созданы;

 
Sergey Dzyublik:

МТ5 (build 2347) Почему такой большой overhead при добавлении по одному элементу в массив с помощью ArrayResize, если память для них была заранее зарезервирована?

Даже такое не помогает.

      ArrayResize(class_array, 1, array_size - 1);
      for(int i = 0; i < array_size; i++){
//         ArrayResize(class_array, i);
         ArrayResize(class_array, i, array_size - 1);

Ерунда какая-то. Вместо ускорения тормоза.


ЗЫ Странно, результат выполнения примера из Документации нулевой.

--- Test Fast: ArrayResize(arr,100000,100000)
1. ArraySize(arr)=100000 Time=0 ms
2. ArraySize(arr)=200000 Time=0 ms
3. ArraySize(arr)=300000 Time=0 ms
---- Test Slow: ArrayResize(slow,100000)
1. ArraySize(slow)=100000 Time=0 ms
2. ArraySize(slow)=200000 Time=0 ms
Документация по MQL5: Операции с массивами / ArrayResize
Документация по MQL5: Операции с массивами / ArrayResize
  • www.mql5.com
При успешном выполнении функция возвращает количество всех элементов, содержащихся в массиве после изменения размера; в противном случае возвращает -1 и массив не меняет размеры. Если ArrayResize() применена к статическому массиву, таймсерии или индикаторному буферу, то размер массива остается прежним – такие массивы не могут быть...
 
Sergey Dzyublik :
Поработал с профайлером в МТ5 (build 2345),
грубо говоря, интересовало почему два алгоритма, дающих в конечном итоге один и тот же результат, выполняются с разной скоростью, просадка в 1.7 раза в режиме оптимизации .


...

К сожалению, это долгое время профилировщик бесполезен для любого важного проекта. Я уже пытался сообщить об этом, но не было никакого интереса со стороны разработчиков.
 
Sergey Dzyublik :

МТ5 (build 2347) Почему такой большой overhead при добавлении по одному элементу в массив с помощью ArrayResize, если память для них была заранее зарезервирована?

Если вы хотите сравнить, это должно быть:

 void test1 ( const int test_count, const int array_size){
   SpeedTest(
   test_count,"Test Class ArrayResize all",
   {
      T class_array[];
       for ( int i = 0 ; i < array_size; i++){
         ArrayResize (class_array,  i );
      }
   }
   )
 
Alain Verleyen:

Если вы хотите сравнить, это должно быть:

С моей стороны сравнивалось то, что должно было быть.
Мне известно сколько элементов будет помещено в массив и вместо того, что бы создавать их все сразу - резервирую память под несозданные.
Проблема в том, что если резервирую память, а создаю элементы массива по одному, то это требует в разы больше времени, чем просто создать все сразу.
Так для стуктур - это в 7 раз медленнее.
А для типов данных класс и int - в два раза медленнее.

Это очень большая разница, которую, как мне кажется, при желании разработчики могут устранить.