Caratteristiche del linguaggio mql5, sottigliezze e tecniche - pagina 53

 
Come sommare molte stringhe velocemente (ad esempio generare un rapporto commerciale in stringa)
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)); // Почему эта строка всегда выполняется заметно быстрее, чем предыдущая?
}

Il risultato

2748404
12678
10388

250 volte più veloce e non è il limite!


HH Il fatto segnato in rosso non può essere spiegato in alcun modo.

 
fxsaber:
Come sommare rapidamente molte stringhe (ad esempio generare un rapporto commerciale in stringa)

Il risultato

250 volte più veloce e non è il limite!


ZS Red segna un fatto che non può essere spiegato in alcun modo.

La particolarità del pool di memoria, quando SumString2 è chiamato per la prima volta, il pool di memoria è "saturo" di memoria dal sistema, quando lo si chiama di nuovo, la memoria non è più richiesta dal sistema.

Raccomando di correggere 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:

Il pooling della memoria è speciale, la prima volta che SumString2 è chiamato nel pool di memoria è "saturato" con la memoria del sistema, la seconda volta, la memoria non è più richiesta dal sistema.

Raccomando di correggere SumString1

Grazie! Potreste riflettere la nozione di un buffer di ricezione almeno in qualche modo nella Guida. Al momento c'è soloStringBufferLen la cui descrizione non dice nulla.

 
fxsaber:

Grazie! Potreste spiegare il concetto di buffer di ricezione almeno in qualche modo nella Guida. Al momento c'è solo StringBufferLen, la cui descrizione non ha senso.

È abbastanza chiaro, stiamo parlando della memoria allocata per le stringhe. È solo che la spiegazione di Elijah della "saturazione della memoria del sistema" è in qualche modo confusa )

A proposito, non sapevo nemmeno di questa caratteristica, che una variabile locale usa la memoria precedentemente allocata. Così si scopre che ha poco senso creare la propria ottimizzazione, a meno che non si parli di un singolo calcolo pesante. Anche la questione del rilascio di questa memoria non è chiara. Viene liberato durante il runtime o solo durante la deinizializzazione?

 
Alexey Navoykov:

È chiaro che stiamo parlando della memoria allocata per le stringhe. È solo che Ilya lo spiega in modo molto complicato sulla "saturazione della memoria del sistema". )

Certo, è comprensibile quando Ilya ha citato il codice. Purtroppo l'Aiuto non dice una parola al riguardo.

A proposito, nemmeno io ero a conoscenza di questa caratteristica specifica: una variabile locale utilizza la memoria allocata in precedenza. Così si scopre che ha poco senso creare la propria ottimizzazione a meno che non si tratti di un singolo calcolo pesante.

Ho appena affrontato un caso simile, quando mi ci sono voluti secondi per formare una stringa. Ma dopo l'ottimizzazione ci ho messo millisecondi. Ma la variante di Ilya è, ovviamente, la più veloce. Se il mio Aiuto fosse stato perfetto, non l'avrei reso tale.

 
fxsaber:

Naturalmente, è comprensibile quando Ilya ha dato il codice. Sfortunatamente, non c'è nessuna parola al riguardo nella Guida.

Mi sono appena imbattuto in un caso simile in cui ci sono voluti secondi per formare una stringa. Ma dopo l'ottimizzazione è stato fatto in millisecondi. Ma la variante di Ilya è, ovviamente, la più veloce. Se il nostro Aiuto fosse stato ideale, non l'avrei reso tale.

Bene, parlando di StringInit, è noto da molto tempo. Lo uso sempre anche per grandi quantità. Se non conosco la lunghezza esatta delle linee da aggiungere, uso una lunghezza approssimativa.

 

Forum sul trading, sistemi di trading automatico e test di strategia

Biblioteche: TesterBenchmark

fxsaber, 2017.08.15 19:31

ZS2 Come mai i freni nel 1648 al primo passaggio di ogni pacchetto? Nel 1643 era così.

Forum sul trading, sistemi di trading automatico e test di strategie di trading

Caratteristiche del linguaggio mql5, sottigliezze e trucchi

fxsaber, 2017.08.15 17:16

Al primo passaggio di un bundle di lavoro Agent (ad esempio, una singola esecuzione del tester), il tempo tra l'esecuzione dell'EA e il primo evento NewTick può richiedere alcuni secondi. Nei passaggi successivi del lotto, questo tempo è zero.

Come se nel 1648 il tester facesse immediatamente un evento NewTick. Il che, ovviamente, è sbagliato.
 

Nel tester, IsStopped() restituisce sempre zero(non falso). Pertanto, è sbagliato aspettarsi che questo flag interagisca con ExpertRemove() come nel mondo reale nel tester.

 
StringInit(Str);
Str = NULL;

La prima linea gira più velocemente della seconda con risultati identici.

 

Forum sul trading, sistemi di trading automatico e test di strategia

Biblioteche: TesterBenchmark

fxsaber, 2017.09.05 09:36

Sostituire stupidamente PositionSelect con PositionGetTicket aumenta la velocità del backtest del 7%!

E questo su un conto di rete!