インジケータを作っていて、あー遅いなー?と思うことがあります。
どこで遅くなっているのか調査する場合、ソースコードを眺めて追いかける良いツールがメタエディタにはついています。
プロファイリング機能です。
これは、プログラムを実行した際、関数毎に時間を計測してくれる機能です。これを使うと、どこで遅くなっているのかが見た目で編別可能になります。
早速使ってみましょう。
遅いなーと思うプログラムをメタエディタで開きます。
ツールバーのプロファイルスタートボタンを押します。下画像の赤丸の箇所です。
■メタエディタ プロファイル開始ボタン
■メタエディタ プロファイル終了ボタン
■メタエディタ プロファイル終了したあとの表示
計測が終了すると、メタエディタ上に実行にかかった時間が表示されます。ソースコード右端にもバーで表示されます。
このバーが大きいほど時間がかかっている個所になりますので、改善方法がないかどうかを調査していく形になります。
MQLにおける速度改善の基本は
・ループの中で余計な処理をしない。
・何度もループしない。
の2点にほぼ集約されます。特にループ外へ処理を追い出す修正は効果が高いため、具体例を挙げたいと思います。
■ダメな例
for(int i = 0; i < rates_total; i++)
{
double currentClose = iClose(NULL,0, 0);
if( currentClose > iClose(NULL, 0, i) )
{
//何か処理
}
}
上記のプログラムでは、iClose(NULL, 0, 0)の結果はループ変数のiに全く影響をうけません。このような処理はループの外に追い出す必要があります。
■修正例
double currentClose = iClose(NULL,0, 0);
for(int i = 0; i < rates_total; i++)
{if( currentClose > iClose(NULL, 0, i) )
{
//何か処理
}
}
この修正で、処理時間が約1/2になります。
修正前処理時間 = iClose処理時間 * 2 * rates_totals
修正後処理時間 = iClose処理時間 + iClose処理時間 * rates_totals
実際プロファイリング機能で見てみましょう。
■ループ内の処理をループ外に追い出した場合の速度差
InnnerCallに対してBeforeCallは処理時間を示すバーの幅が半分になっていることが見て取れるかと思います。
このようにループの中の処理見直しは改善効果が高いため、もし表示が遅いなーということがあれば、ループ内処理を中心に見直すことになります。
プロファイリングといえば、以前MQLのクラスメソッドの呼び出しが異常に遅い!と文句たらたらだったことがあります。
[MT4プログラミング]クラスメソッドの呼び出しにご用心
そろそろ治ってないかなーとおもい、プロファイリングの記事を書くついでに、MT4 Build971にて再計測してみました。使用したプログラムは次の通りです。
//------------------------------------------------------------------
// 速度テスト
#property copyright "Copyright 2016, Daisuke"
#property link "http://mt4program.blogspot.jp/"
#property version "1.00"
#property strict
#property indicator_chart_window
#define MAXCOUNT 10000
class COpen
{
public:
void IndirectionOpen()
{
iOpen(NULL, 0, 1);
}
};
COpen m_open;
COpen *m_pOpen;
//------------------------------------------------------------------
// 初期化
int OnInit()
{
m_pOpen = GetPointer(m_open);
DirectCall();
IndirectionCall();
ClassCall();
ClassPointerCall();
return(INIT_SUCCEEDED);
}
//------------------------------------------------------------------
// 直接呼出し
void DirectCall()
{
for(int i = 0; i < MAXCOUNT; i++)
{
iOpen(NULL, 0, 1);
}
}
//------------------------------------------------------------------
// 間接呼出し
void IndirectionCall()
{
for(int i = 0; i < MAXCOUNT; i++)
{
IndirectionOpen();
}
}
void IndirectionOpen()
{
iOpen(NULL, 0, 1);
}
//------------------------------------------------------------------
// クラス呼び出し
void ClassCall()
{
for(int i = 0; i < MAXCOUNT; i++)
{
m_open.IndirectionOpen();
}
}
//------------------------------------------------------------------
// クラス呼び出し
void ClassPointerCall()
{
for(int i = 0; i < MAXCOUNT; i++)
{
m_pOpen.IndirectionOpen();
}
}
//------------------------------------------------------------------
// 計算処理
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[])
{
//---
//--- return value of prev_calculated for next call
return(rates_total);
}
//+------------------------------------------------------------------+
OnInitの中で、次の4つの関数を呼び出して速度比較してみます。
・直接iOpenをコール(DirectCall)
・一回関数をはさむ(IndirectionCall)
・クラスの直接参照(ClassCall)
・クラスのポインタ参照(ClassPointerCall)
結果は次の形になりました。
MQL プロファイラレポート - SpeedTest.mq4 | |||||
---|---|---|---|---|---|
関数 | 行 | カウント | 時間 | パーセント | グラフ |
OnInit | 27 | 1 | 2 422 | 99.71% | |
COpen::IndirectionOpen | 20000 | 730 | 30.05% | ||
IndirectionCall | 31 | 1 | 686 | 28.24% | |
ClassCall | 32 | 1 | 686 | 28.24% | |
ClassPointerCall | 33 | 1 | 686 | 28.24% | |
iOpen | 40000 | 419 | 17.25% | ||
IndirectionOpen | 54 | 10000 | 365 | 15.03% | |
DirectCall | 30 | 1 | 363 | 14.94% | |
@global_initializations | 1 | 6 | 0.25% | ||
OnCalculate | 86 | 26 | 1 | 0.04% | |
COpen::~COpen | 1 | 0 | 0.00% | ||
COpen::COpen | 20 | 1 | 0 | 0.00% | |
@global_deinitializations | 1 | 0 | 0.00% | ||
GetPointer | 29 | 1 | 0 | 0.00% | |
Copyright 2001-2013, MetaQuotes Software Corp. |
直接参照が一番早いのは当然として、関数呼び出し~クラス呼び出しについては差がなくなっています。以前はクラス呼び出しが異常なほど(それこそ10倍ぐらい)遅かったのですが改善したようです。
これでもっと積極的にクラスが利用できます。
「MT4でFXを勝ち抜く研究をするブログ」で公開している無料インジケータは、こちらの一覧から。
インジケータ一覧
Twitterもよろしくお願いします。
https://twitter.com/mt4program
ブログランキングにご協力よろしくお願いします。m(._.)m
にほんブログ村 |
お約束ですが、本ブログは、投資に対する利益を約束する物ではありません。最終的には自己責任によるご判断よろしくお願いいたします。