Caractéristiques du langage mql5, subtilités et techniques - page 53

 
Comment additionner rapidement de nombreuses chaînes (par exemple, générer un rapport commercial en chaîne)
class SUM_STRING
{
protected:
  uchar Data[];
    
public:
  SUM_STRING( const int Reserve = 0 )
  {
    ::ArrayResize(this.Data, 1, Reserve);
  }

  void operator +=( const string Str )
  {
    ::StringToCharArray(Str, this.Data, ::ArraySize(this.Data) - 1);
  }
  
  const string Get( void ) const
  {
    return(::CharArrayToString(this.Data));
  }
};

// Классическое складывание
ulong SumString1( string TmpStr, const int Amount )
{
  const ulong StartTime = GetMicrosecondCount();

  string Str = "";

  for (int i = 0; i < Amount; i++)
    Str += TmpStr;

  return(GetMicrosecondCount() - StartTime);
}

// Быстрое складывание
ulong SumString2( string TmpStr, const int Amount )
{
  const ulong StartTime = GetMicrosecondCount();

  SUM_STRING SumStr(Amount * StringLen(TmpStr) + 1);

  for (int i = 0; i < Amount; i++)
    SumStr += TmpStr;

  const string Str = SumStr.Get();

  return(GetMicrosecondCount() - StartTime);
}

// #property script_show_inputs

input int inLen = 400;    // Длина строки, которую будем добавлять
input int inAmount = 1 e4; // Сколько раз будем складывать

// Как быстро сложить много строк (например, сгенерировать торговый отчет в string)
void OnStart()
{  
  string Str;
  
  StringInit(Str, inLen, 1);
  
  Print(SumString1(Str, inAmount)); // Время классического решения
  Print(SumString2(Str, inAmount)); // Время альтернативного решения
  Print(SumString2(Str, inAmount)); // Почему эта строка всегда выполняется заметно быстрее, чем предыдущая?
}

Le résultat

2748404
12678
10388

250 fois plus rapide et ce n'est pas la limite !


HH Le fait marqué en rouge ne peut être expliqué d'aucune manière.

 
fxsaber:
Comment additionner rapidement plusieurs chaînes de caractères (par exemple, générer un rapport commercial en chaîne)

Le résultat

250 fois plus rapide et ce n'est pas la limite !


ZS Rouge marque un fait qui ne peut être expliqué d'aucune manière.

La particularité du pool de mémoire, lorsque SumString2 est appelé pour la première fois, le pool de mémoire est "saturé" avec la mémoire du système, lorsque vous l'appelez à nouveau, la mémoire n'est plus demandée au système.

Je recommande de corriger SumString1

ulong SumString1( string TmpStr, const int Amount )
{
  const ulong StartTime = GetMicrosecondCount();

  string Str;
  StringInit(Str,Amount * StringLen(TmpStr) + 1);            << обеспечим строке приёмный буфер

  for (int i = 0; i < Amount; i++)
    Str += TmpStr;

  return(GetMicrosecondCount() - StartTime);
}
 
Ilyas:

La mise en commun de la mémoire est spéciale, la première fois que SumString2 est appelé dans le pool de mémoire, il est "saturé" avec la mémoire du système, la deuxième fois, la mémoire n'est plus demandée au système.

Je recommande de corriger SumString1

Merci ! Pourriez-vous s'il vous plaît refléter la notion de tampon de réception au moins d'une manière ou d'une autre dans l'aide. Pour l'instant, il n'y a queStringBufferLen dont la description ne dit rien.

 
fxsaber:

Merci ! Pourriez-vous expliquer le concept de tampon de réception au moins d'une manière ou d'une autre dans l'aide. Actuellement, il n'y a que StringBufferLen, dont la description n'a aucun sens.

C'est très clair, nous parlons de la mémoire allouée à la chaîne de caractères. C'est juste que l'explication d'Elijah sur la "saturation de la mémoire du système" est quelque peu confuse. )

À propos, je ne savais pas non plus qu'une variable locale utilisait de la mémoire précédemment allouée. Il s'avère donc qu'il n'y a pas grand intérêt à faire sa propre optimisation, sauf s'il s'agit d'un seul calcul lourd. La question de la libération de cette mémoire n'est pas non plus claire. Est-il libéré pendant l'exécution ou seulement pendant la désinitialisation ?

 
Alexey Navoykov:

C'est clair, nous parlons de la mémoire allouée pour la chaîne de caractères. C'est juste qu'Ilya l'explique de manière très compliquée à propos de la "saturation de la mémoire du système". )

Bien sûr, c'est compréhensible qu'Ilya ait cité le code. Malheureusement, il n'en dit pas un mot dans l'aide.

D'ailleurs, je n'étais pas non plus au courant de cette particularité : une variable locale utilise la mémoire allouée précédemment. Il s'avère donc qu'il n'y a guère de sens à créer votre propre optimisation, sauf si nous avons affaire à un seul calcul lourd.

Je viens de faire face à un tel cas où il m'a fallu quelques secondes pour former une chaîne. Mais après l'optimisation, ça m'a pris des millisecondes. Mais la variante d'Ilya est, bien sûr, la plus rapide. Si mon aide était parfaite, je ne l'aurais pas fait.

 
fxsaber:

Bien sûr, il est compréhensible qu'Ilya ait donné le code. Malheureusement, il n'y a pas de mot à ce sujet dans l'aide.

Je viens de rencontrer un tel cas où il fallait quelques secondes pour former une chaîne. Mais après l'optimisation, cela s'est fait en quelques millisecondes. Mais la variante d'Ilya est, bien sûr, la plus rapide. Si notre aide était idéale, je ne l'aurais pas fait.

Eh bien, en parlant de StringInit, c'est connu depuis longtemps. Je l'utilise aussi toujours pour les grandes quantités. Si je ne connais pas la longueur exacte des lignes à ajouter, j'utilise la longueur approximative.

 

Forum sur le trading, les systèmes de trading automatisés et les tests de stratégie

Bibliothèques : TesterBenchmark

fxsaber, 2017.08.15 19:31

ZS2 C'est quoi ces freins en 1648 au premier passage de chaque paquet ? En 1643, c'était comme ça.

Forum sur le trading, les systèmes de trading automatisé et les tests de stratégies de trading

Caractéristiques du langage mql5, subtilités et astuces

fxsaber, 2017.08.15 17:16

Lors du premier passage d'un lot de tâches de l'agent (par exemple, un seul test), le délai entre l'exécution de l'EA et le premier événement NewTick peut prendre quelques secondes. Lors des passages suivants du pack, ce temps est égal à zéro.

Comme si, en 1648, le testeur créait immédiatement un événement NewTick. Ce qui, bien sûr, est faux.
 

Dans le testeur, IsStopped() renvoie toujours zéro(pas faux). Par conséquent, il est faux de s'attendre à ce que ce drapeau interagisse avec ExpertRemove() comme dans le monde réel dans le testeur.

 
StringInit(Str);
Str = NULL;

La première ligne s'exécute plus rapidement que la seconde avec des résultats identiques.

 

Forum sur le trading, les systèmes de trading automatisés et les tests de stratégie

Bibliothèques : TesterBenchmark

fxsaber, 2017.09.05 09:36

Le remplacement stupide de PositionSelect par PositionGetTicket augmente la vitesse du backtest de 7% !

Et ce, sur un compte de compensation !
Raison: