mql5语言的特点、微妙之处以及技巧 - 页 49

 
fxsaber:

如果你在if、else、while、for、do这些词后面立即按TAB键,会有一点额外的结构......


f*cking hell... great, after 5 years of knowing mql - I found out.

 

从SD中关于提出的一个问题 的谈话中得出的结论。

事实证明,给一个字符串变量赋值是一个非常昂贵的操作。

如此昂贵,以至于如果可能的话最好避免它,直到开发人员在编译器中改进这一点,而这似乎不会很快发生。


举个例子,如果你在FIBO上运行一个月的真实tick运行,大约是100万ticks。如果你在每个tick上得到PositionGetString的值,并与之进行比较,性能是可以接受的,但如果你在比较之前先把函数的结果赋给一个字符串变量,那么运行的时间会增加一秒左右。


如果这看起来是一件小事,那是错误的设想。当这样的EA在优化模式下运行几千次时,多出的这一秒就会转化为额外的几个小时的等待时间。也就是说,一个无害的字符串赋值可能会在优化过程中造成额外的时间等待。要小心并考虑到这种细微差别。


在kodobase中,有一个小工具,可以让你在同一交易逻辑的不同实现中检测到这种故障。编写快速代码。

 
fxsaber:

从SD中关于提出的一个问题 的谈话中得出的结论。

事实证明,给一个字符串变量赋值是一个非常昂贵的操作。

如此昂贵,以至于在开发人员改进编译器中的这一点之前,最好尽可能地避免它,而这似乎不会很快发生。


举个例子,如果你在FIBO上运行一个月的真实tick运行,将是大约100万tick。如果你在每个tick上得到PositionGetString的值,并与之进行比较,性能是可以接受的,但如果你在比较之前先把函数的结果赋给一个字符串变量,那么运行的时间会增加一秒左右。


如果这看起来是一件小事,那是错误的设想。当这样的EA在优化模式下运行几千次时,多出的这一秒就会转化为额外的几个小时的等待时间。也就是说,一个无害的字符串赋值可能会在优化过程中造成额外的时间等待。要小心并考虑到这种细微差别。


在kodobase中,有一个小工具,可以让你在同一交易逻辑的不同实现中检测到这种故障。写一个快速代码。

谢谢你,我认为这是不可能的。我将在今后的发展中考虑到这一点

 

一个简单的睡前谜语,为什么会有黄色的结果?

struct INT
{
  int Array[];
  
  INT()
  {
    Print(__FUNCTION__); // до сюда не дойдет
  }
};

void OnStart()
{
  INT i = {0};
  
  Print(ArrayResize(i.Array, 5)); // -1
}
 
fxsaber:

一个简单的睡前谜语,为什么会有黄色的结果?

因为这个结构是用零打包的,不是通过构造器,所以数组结构的初始化不正确,arrayresize 不喜欢这样的数组,我的代码在这样的调整大小时崩溃了。
 
组合器
因为结构里装的是零,而不是构造函数,所以数组结构的初始化是不正确的,arrayresize不喜欢这样的数组,我的代码在这样的resize上根本就崩溃了。

这是一件好事,每个人都知道这件事。

 
Slava:

它指的是GetMicrosecondCount。没有确切的方法来判断它是否拖累了服务器。它可能有间接影响。因此,最好使用系统中的GetTickCount

GetMicrosecondCount用于测量代码执行的短时期。要测量大量的OnTick执行,最好使用GetTickCount。

当你得到稳定的结果时,尝试使用GetMicrosecondsCount而不是GetTickCount。你 要在这里告诉我。也许我担心得太多了。

你的假设是正确的,多次调用GetMicrosecondsCount会在测试器中造成可怕的滞后。然而,GetTickCount 有同样的效果。
 
fxsaber:

从SD中关于提出的一个问题 的谈话中得出的结论。

事实证明,给一个字符串变量赋值是一个非常昂贵的操作。

如此昂贵,以至于在开发人员改进编译器中的这一点之前,最好尽可能地避免它,而这似乎是一个漫长的过程。


举个例子,如果你在FIBO上运行一个月的真实tick运行,大约是100万ticks。如果你在每个tick上得到PositionGetString的值,并与之进行比较,性能是可以接受的,但如果你在比较之前先把函数的结果赋给一个字符串变量,那么运行的时间会增加一秒左右。


如果这看起来是一件小事,那是错误的设想。当这样的EA在优化模式下运行几千次时,多出的这一秒就会转化为额外的几个小时的等待时间。也就是说,一个无害的字符串赋值可能会在优化过程中造成额外的时间等待。要小心并考虑到这种细微差别。


在kodobase中,有一个小工具,可以让你在同一交易逻辑的不同实现中检测到这种故障。写一个快速代码。

struct STRUCT
{
  string Str;
  
  string Get() const { return(this.Str); }
};

void OnStart()
{
  STRUCT Struct;
  
  Print(Struct.Str);
  Print(Struct.Get()); // Выполняется гораздо дольше, чем предыдущая строка
}
 
fxsaber:

事实证明,给一个字符串变量赋值是一个非常昂贵的操作。

...

如果你在比较前先把函数的结果赋给一个字符串变量,然后再进行比较,那么运行时间将增加约一秒钟。

在我看来,问题不在于昂贵的赋值,而在于编译器由于某种原因没有把这个不必要的赋值从代码中删掉,尽管它应该这样做。也就是说,在两种情况下,编译后的代码应该是一样的。
 
阿列克谢-纳沃伊科夫
根据我的理解,问题不在于昂贵的赋值,而在于编译器出于某种原因没有将这种不必要的赋值从代码中删去,尽管它应该这样做。即编译后的代码在两种情况下应该是一样的。

这是个小问题。是的,编译器优化器还不知道如何优化这种字符串时刻。但是,慢下来的问题就在字符串的分配上。

编写不能被编译器优化的代码,同时在其中进行赋值。你就会看到什么是放缓。

通过函数读取结构的字符串字段的例子正是MT4/5中读取位置属性 的实现方式。

在MT4中,如果在MT5中实现了同样的OrderSymbol(),就会出现制动。开发者自己试图通过链接传递给他们的函数字符串。

因此,如果你写下这样的内容

if ((OrderSymbol() == Symb) && (OrderMagicNumber == Magic))

把OrderSymbol()条件推到一般条件的末尾总是更好。


当我使用TesterBench时,我注意到在看似光滑的表面有明显的减速。