Непонятки с CHashMap из стандартной библиотеки - страница 3

 

У меня вот что на скору руку получилось:

//+------------------------------------------------------------------+
//|                                                      testMap.mq5 |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"

#include <Generic\HashMap.mqh>

class EnchancedRand
{
public:
   EnchancedRand(int iMax) : _Max(iMax)
   {
      _Turns = int(MathCeil(MathLog(iMax) / MathLog(2))) / 15 + 1;      
   }
   
   int Get()
   {
      int Answ = 0;
      for(int I = 0; I < _Turns; ++I)
      {
         Answ <<= 15;
         Answ += MathRand();
      }
      
      return Answ % _Max;
   }
private:
   int _Max;
   int _Turns;
};

int RandArray[];
int Turns = 1000000;
int Shuffles = 1000000;

void FillRandArray(int iShuffles)
{
   ArrayResize(RandArray, Turns);

   for(int I = 0; I < Turns; ++I)
      RandArray[I] = I;
      
   int Pos1, Pos2, Val;
      
   EnchancedRand ShuffleRand(Turns);  
      
   // Shuffle
   for(int I = 0; I < iShuffles; ++I)
   {
      Pos1 = ShuffleRand.Get();
      Pos2 = ShuffleRand.Get();
      Val = RandArray[Pos1];
      RandArray[Pos1] = RandArray[Pos2];
      RandArray[Pos2] = Val;
   }
}

void RunTests(int iShuffle, int iLaps)
{
   FillRandArray(iShuffle);

   ulong start = 0, total = 0;

   for(int I = 0; I < iLaps; ++I)
   {   
      CHashMap<int, int> TestMap;      
      
      start = GetMicrosecondCount();              
      for(int J = 0; J < Turns; ++J)
      {
         TestMap.Add(RandArray[J], 1);
      }      
      total += GetMicrosecondCount() - start;
   }
   
   PrintFormat("%d laps with shuffle %d: %I64u mks (avg time: %I64u mks)", iLaps, iShuffle, total, total / iLaps);
}

void OnStart()
{
   for(int I = 0; I <= Shuffles; I += Shuffles / 10)
   {
      RunTests(I, 10);
   }
}

Вот что выдает:

10 laps with shuffle 0: 1003427 mks (avg time: 100342 mks)

10 laps with shuffle 100000: 1189368 mks (avg time: 118936 mks)

10 laps with shuffle 200000: 1263161 mks (avg time: 126316 mks)

10 laps with shuffle 300000: 1269436 mks (avg time: 126943 mks)

10 laps with shuffle 400000: 1332494 mks (avg time: 133249 mks)

10 laps with shuffle 500000: 1318475 mks (avg time: 131847 mks)

10 laps with shuffle 600000: 1383286 mks (avg time: 138328 mks)

10 laps with shuffle 700000: 1306930 mks (avg time: 130693 mks)

10 laps with shuffle 800000: 1362641 mks (avg time: 136264 mks)

10 laps with shuffle 900000: 1432880 mks (avg time: 143288 mks)

10 laps with shuffle 1000000: 1414064 mks (avg time: 141406 mks)

10 laps with shuffle 0: 1006673 mks (avg time: 100667 mks)

10 laps with shuffle 100000: 1221832 mks (avg time: 122183 mks)

10 laps with shuffle 200000: 1257803 mks (avg time: 125780 mks)

10 laps with shuffle 300000: 1273321 mks (avg time: 127332 mks)

10 laps with shuffle 400000: 1340463 mks (avg time: 134046 mks)

10 laps with shuffle 500000: 1346491 mks (avg time: 134649 mks)

10 laps with shuffle 600000: 1320104 mks (avg time: 132010 mks)

10 laps with shuffle 700000: 1368562 mks (avg time: 136856 mks)

10 laps with shuffle 800000: 1403330 mks (avg time: 140333 mks)

10 laps with shuffle 900000: 1336840 mks (avg time: 133684 mks)

10 laps with shuffle 1000000: 1396604 mks (avg time: 139660 mks)

Ожидаемо, с ростом неупорядоченности входного массива растёт время вставки (но не сильно).

Любопытно бы Dictionary на этом тесте прогнать.

 
Mesaoria:

Ожидаемо, с ростом неупорядоченности входного массива растёт время вставки (но не сильно).

Любопытно бы Dictionary на этом тесте прогнать.

Будет значительно медленнее. Зато у него есть возможность пройтись по всем элементам, а у CHashMap только доступ по ключу.

 
Alexey Volchanskiy:

При попытке скомпилировать Cdictionary под МТ4 получаю ошибку компиляции

'union' - declaration without type dictionary2.mqh 95 4

'casting_struct' - declaration without type dictionary2.mqh 111 4

2 error(s), 0 warning(s) 3 1

Я не понимаю, MQL4 не поддерживает union, что ли??? В MQL5 все компилится без проблем. И что вообще означает дурацкое сообщение "declaration without type"???

--------------

Может property strict поможет?

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

 
Нужно потестить с версиями в аттаче для мт4 и мт5 соответственно:
Файлы:
 

Вообще тестировать словари на вставку и удаление очень странное занятие, т.к. в конечном счете все эти тесты сводятся к замеру производительности ArrayResize(). У словарей есть такое замечательное свойство capacity, которое позволяет избегать динамического перераспределения памяти и загонять стрелку скорости в космос. Поэтому если в тесте пишется: добавить 1 000 000 элементов в словарь без capacity - это как-то несерьезно, непонятно что измеряется в итоге. Что касается CDictionary то там есть еще одна интересная особенность: после формирования коллекции можно указать AutoResize(false). Это позволяет загнать стрелку в космос не только при добавлении но и при удалении элементов.

Т.е. что бы провести грамотное тестирование нужно очень хорошо разбираться в особенностях алгоритма и понимать как организуются данные на внутреннем уровне. Если такого понимания нет, то низкая скорость это почти всегда результат "вы просто не умеете это готовить". 

 
Vasiliy Sokolov:

Вообще тестировать словари на вставку и удаление очень странное занятие, т.к. в конечном счете все эти тесты сводятся к замеру производительности ArrayResize().

Мда.

 
Vasiliy Sokolov:
Нужно потестить с версиями в аттаче для мт4 и мт5 соответственно:

Для МТ5 компилируется, для МТ4 старые проблемы

'DictionaryMT4.mqh' DictionaryMT4.mqh 1 1

'Object.mqh' Object.mqh 1 1

'StdLibErr.mqh' StdLibErr.mqh 1 1

'List.mqh' List.mqh 1 1

'union' - declaration without type DictionaryMT4.mqh 105 4

'casting' - declaration without type DictionaryMT4.mqh 109 5

2 error(s), 0 warning(s) 3 1

Что за хрень такая....?
 
Alexey Volchanskiy:

Для МТ5 компилируется, для МТ4 старые проблемы

'DictionaryMT4.mqh' DictionaryMT4.mqh 1 1

'Object.mqh' Object.mqh 1 1

'StdLibErr.mqh' StdLibErr.mqh 1 1

'List.mqh' List.mqh 1 1

'union' - declaration without type DictionaryMT4.mqh 105 4

'casting' - declaration without type DictionaryMT4.mqh 109 5

2 error(s), 0 warning(s) 3 1

Что за хрень такая....?
У меня версия, которая компилируется. Буду у компа - гляну. 
 
Artyom Trishkin:
У меня версия, которая компилируется. Буду у компа - гляну. 

Да, посмотри пожалуйста. Сейчас перекинул папку Include/Generic в МТ4, то же самое - не хочет компилировать union! Похоже, надо в СД писать.

В справке большая статья про union, то есть должны поддерживаться. Билд последний, 1090.

Сделал простейший скрипт, та же дурацкая ошибка

'union' - declaration without type TestUnion.mq4 11 1

union utest
{
    long l;
    double d;
};

void OnStart()
{
   
}
 
Alexey Volchanskiy:

Да, посмотри пожалуйста. Сейчас перекинул папку Include/Generic в МТ4, то же самое - не хочет компилировать union! Похоже, надо в СД писать.

В справке большая статья про union, то есть должны поддерживаться. Билд последний, 1090.

Сделал простейший скрипт, та же дурацкая ошибка

'union' - declaration without type TestUnion.mq4 11 1

union utest
{
    long l;
    double d;
};

void OnStart()
{
   
}

Зашибись! По какому-то наитию решил попробовать скомпилировать код из предыдущего поста под редактором из МТ5.

'TestUnion.mq4' TestUnion.mq4 1 1

0 error(s), 0 warning(s), compile time: 401 msec 1 1

!!!!!!!! И после этого они говорят, что компилятор МТ4 одинаковый в МТ4 и МТ5!!

Сейчас попробую и остальное там скомпилить

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