2015年7月30日木曜日

[MT4プログラミング]クラスメソッドの呼び出しにご用心

classmethod.png
MT4プログラムで少々はまったので・・・・

私はクラス大好きなので、クラスを使用してインジケータを作っています。
さて、ループの中でクラスメソッドを呼び出してインジケータを作っていたのですが、なぜか遅い・・・・。

MetaEditorにはデバッグ実行時の各メソッドの時間を測定するプロファイリング機能があります。
metaprofile.png
このボタンです。

計測してみると・・・。GetPriceというメソッドが全体の40%の時間を占めてします。
メソッドの中身は、GetPriceという関数を呼び出しているだけです。
double CIndicatorBaseData::GetPrice(
int i,      //インデックス
ENUM_APPLIED_PRICE maPrice    //取得価格
)
{
if( i < 0 || i >= m_rateTotal )
{
return 0;
}
return GetPrice(m_open[i], m_close[i], m_high[i], m_low[i], maPrice);
}


このメソッドの中で呼び出しているGetPriceは全体の4%しか占めていませんから、残り35%を、ここの処理が占めています・・・。
判らない。何が遅いのかわからない・・・・・・。

もしかしてMQL4ってクラスメソッドの呼び出しオーバヘッドがものすごく大きいのでは?と思い、クラスのメンバを直接公開して(カプセル化の原則に違反しますが・・。パフォーマンスには変えられません・・・)アクセスするようにしたところ・・・。

解消されました。
・・・・・意味わからん><

クラスポインタへのアクセスが遅いのかと思いきや、そうでもないらしく単純にクラスメソッドの呼び出しが遅い様子。ざっくりと通常の関数に比べて10倍ほど遅い形です。

70万回も回されると、影響が出てきてしまいます。
EAのように処理データを必要な範囲に抑えてしまえる場合は、バックテスト時以外はあまり影響がありませんが、インジケータで大量のチャートバー数を表示していると一挙に効いてきます。

うーん。ループ内の処理はクラス化せずに、関数で処理したほうがパフォーマンス的にはよさそうです。

オブジェクト指向大好きっこな私にとっては苦痛ですが、仕方がないかなぁといったところです。MQLにそこまで本格的なプログラミングをするなという事かもしれません。