Características da linguagem mql5, subtilezas e técnicas - página 53

 
Como somar muitas cordas rapidamente (por exemplo, gerar um relatório comercial em cadeia)
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)); // Почему эта строка всегда выполняется заметно быстрее, чем предыдущая?
}

O resultado

2748404
12678
10388

250 vezes mais rápido e isso não é o limite!


HH O fato marcado em vermelho não pode ser explicado de forma alguma.

 
fxsaber:
Como somar rapidamente muitas cordas (por exemplo, gerar um relatório comercial em cadeia)

O resultado

250 vezes mais rápido e isso não é o limite!


ZS Vermelho marca um fato que não pode ser explicado de forma alguma.

A peculiaridade do pool de memória, quando o SumString2 é chamado pela primeira vez, o pool de memória é "saturado" com memória do sistema, na segunda vez, a memória não é mais solicitada ao sistema.

Eu recomendo corrigir 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:

O pooling de memória é especial, a primeira vez que o SumString2 é chamado para o pool de memória é "saturado" com memória do sistema, a segunda vez a memória não é solicitada ao sistema novamente.

Eu recomendo corrigir SumString1

Obrigado! Pode reflectir a noção de um buffer de recepção, pelo menos de alguma forma, na Ajuda. Neste momento só existe oStringBufferLen que não diz nada.

 
fxsaber:

Obrigado! Poderia, por favor, explicar o conceito de receber buffer, pelo menos de alguma forma, na Ajuda. Neste momento só existe o StringBufferLen, cuja descrição não faz qualquer sentido.

É bastante claro, estamos a falar de memória alocada para a stringing. É apenas a explicação de Elijah de "saturação de memória do sistema" é de alguma forma confusa. )

A propósito, eu também não sabia sobre tal recurso, que uma variável local usa memória previamente alocada. Então acontece que há pouco sentido em criar a sua própria otimização, a menos que estejamos falando de um único cálculo pesado. A questão da libertação desta memória também não é clara. É libertado durante a execução ou apenas durante a desinicialização?

 
Alexey Navoykov:

Está claro, estamos a falar da memória alocada para a string. É que Ilya explica isso de uma forma muito complicada sobre a "saturação de memória do sistema". )

Claro, é compreensível quando o Ilya citou o código. Infelizmente, ele não diz uma palavra sobre isso na Ajuda.

A propósito, eu também não estava ciente desta característica específica: uma variável local usa memória alocada anteriormente. Então, acontece que não faz muito sentido criar a sua própria otimização, a menos que lidemos com um único cálculo pesado.

Enfrentei um caso destes quando demorei segundos a formar um cordel. Mas depois da optimização levou-me milissegundos. Mas a variante do Ilya é, claro, a mais rápida. Se a minha ajuda fosse perfeita, eu não o teria feito.

 
fxsaber:

Claro, é compreensível quando Ilya deu o código. Infelizmente, não há nenhuma palavra sobre isso na Ajuda.

Deparei-me com um caso destes quando demorou segundos a formar um cordel. Mas após a optimização foi feito em milissegundos. Mas a variante do Ilya é, claro, a mais rápida. Se a nossa ajuda fosse o ideal, eu não o teria feito.

Bem, por falar em StringInit, já é conhecido há muito tempo. Eu também o uso sempre para grandes quantidades. Se eu não sei o comprimento exato das linhas a serem adicionadas, eu uso o comprimento aproximado.

 

Fórum sobre negociação, sistemas de negociação automatizados e testes estratégicos

Bibliotecas: TesterBenchmark

fxsaber, 2017.08.15 19:31

ZS2 Para que são os freios em 1648 na primeira passagem de cada pacote? Em 1643, foi assim.

Fórum sobre negociação, sistemas de negociação automatizados e testes de estratégia de negociação

Características da linguagem mql5, subtilezas e truques

fxsaber, 2017.08.15 17:16

Na primeira passagem de um pacote de trabalho de Agente (por exemplo, uma única corrida de teste), o tempo entre a corrida da EA e o primeiro evento NewTick pode levar alguns segundos. Nas passagens subsequentes do pacote, desta vez é zero.

Como se em 1648 o testador fizesse imediatamente um evento NewTick. O que, é claro, está errado.
 

No testador, IsStopped() sempre retorna zero(não falso). Portanto, é errado esperar que esta bandeira interaja com ExpertRemove() como no mundo real no testador.

 
StringInit(Str);
Str = NULL;

A primeira linha corre mais rápido que a segunda com resultados idênticos.

 

Fórum sobre negociação, sistemas de negociação automatizados e testes estratégicos

Bibliotecas: TesterBenchmark

fxsaber, 2017.09.05 09:36

Substituir estupidamente PositionSelect por PositionGetTicket aumenta a velocidade de retrocesso em 7%!

E isso é numa conta de rede!