チャート上の個々のテキストラベルとビットマップのパフォーマンステスト

 

ディスカッションの開始はこちら: https://www.mql5.com/ru/forum/1111/page989#comment_480838

当初は「ビットマップはテキストオブジェクトの数倍・数十倍遅い」という話でしたが、議論とテストソースの確認を経て、明らかにビットマップの方が速いことが判明しました。

テストは、Windows 8 x64の64bit MetaTrader 5で、弱いNVIDIA GeForce GT 640Mビデオカードで行われました。以下は、テストスクリプトで得られた結果(時間が短いほど良い)です。

2013.04.27 22:21:50	BenchmarkLabel (EURUSD,M15)	Тестирование завершено
2013.04.27 22:21:50	BenchmarkLabel (EURUSD,M15)	5. Время обновления текста и позиций у битмапа без прозрачности = 15007 ms
2013.04.27 22:21:35	BenchmarkLabel (EURUSD,M15)	4. Время обновления текста и позиций у битмапа с прозрачностью = 15257 ms
2013.04.27 22:21:20	BenchmarkLabel (EURUSD,M15)	3. Время обновления текста и позиций у меток со чтением = 16739 ms
2013.04.27 22:21:03	BenchmarkLabel (EURUSD,M15)	2. Время обновления текста и позиций у меток без чтения = 18845 ms
2013.04.27 22:20:44	BenchmarkLabel (EURUSD,M15)	1. Время обновления текста у меток без чтения = 21497 ms
2013.04.27 22:20:23	BenchmarkLabel (EURUSD,M15)	0. Время разогрева динамических очередей без визуализации = 124 ms
2013.04.27 22:20:23	BenchmarkLabel (EURUSD,M15)	Для корректного теста подберите размер окна 1024 x 768 пикселей, без индикаторов, не трогайте ничего, не сворачивайте и не закрывайте окна
2013.04.27 22:20:23	BenchmarkLabel (EURUSD,M15)	Разрешение чарта: 1020 x 761 пикселей

ラベルを使った作業は、ビットマップを使った作業に比べ、約60%も遅いことがわかります。

以下は、誰でもダウンロードできるテストスクリプトで、自分でテストして結果を投稿することができます。

#property script_show_inputs

//---
input int   inRefreshCount=5000;
input int   inNumberOfLabels=26;
input color inTextColor=clrRed;

uint ExtCanvas[];
int  ExtBitmapWidth=20;             // вычислится автоматически
int  ExtBitmapHeight=20;            // вычислится автоматически
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- выведем разделитель для журнала и инициализируем рандом
   Print("");
   MathSrand(GetTickCount());
//--- покажем разрешение чарта
   Print("Разрешение чарта: ",ChartGetInteger(ChartID(),CHART_WIDTH_IN_PIXELS,0)," x ",ChartGetInteger(ChartID(),CHART_HEIGHT_IN_PIXELS,0)," пикселей");
   Print("Для корректного теста подберите размер окна 1024 x 768 пикселей, без индикаторов, не трогайте ничего, не сворачивайте и не закрывайте окна");
//--- cоздание меток
   CreateLabels();
   ChartRedraw(0);
//--- 0. холостой разогрев динамических очередей
   string name;
   uint   start=GetTickCount();

   for(int i=0;i<inRefreshCount && !IsStopped();i++)
     {
      for(int j=0;j<inNumberOfLabels;j++)
        {
         name="ObjectLabel#"+IntegerToString(j);
         ObjectSetString(0,name,OBJPROP_TEXT,IntegerToString(MathRand()));
        }
     }
   ChartRedraw(0);
   Print("0. Время разогрева динамических очередей без визуализации = ",GetTickCount()-start," ms");
//--- 1. замерим скорость обновление меток (текст)
   start=GetTickCount();

   for(int i=0;i<inRefreshCount && !IsStopped();i++)
     {
      for(int j=0;j<inNumberOfLabels;j++)
        {
         name="ObjectLabel#"+IntegerToString(j);
         ObjectSetString(0,name,OBJPROP_TEXT,IntegerToString(MathRand()));
        }
      ChartRedraw(0);
     }
   Print("1. Время обновления текста у меток без чтения = ",GetTickCount()-start," ms");
//--- 2. замерим скорость обновление меток (текст + смена позиций)
   start=GetTickCount();

   for(int i=0;i<inRefreshCount && !IsStopped();i++)
     {
      for(int j=0;j<inNumberOfLabels;j++)
        {
         name="ObjectLabel#"+IntegerToString(j);
         ObjectSetInteger(0,name,OBJPROP_XDISTANCE,10+j*10+(i&3));
         ObjectSetInteger(0,name,OBJPROP_YDISTANCE,10+j*10+(i&3));
         ObjectSetString(0,name,OBJPROP_TEXT,IntegerToString(MathRand()));
        }
      ChartRedraw(0);
     }
   Print("2. Время обновления текста и позиций у меток без чтения = ",GetTickCount()-start," ms");
//--- 3. замерим скорость обновление меток (текст + смена позиций) со чтением позиций
   start=GetTickCount();

   for(int i=0;i<inRefreshCount && !IsStopped();i++)
     {
      for(int j=0;j<inNumberOfLabels;j++)
        {
         name="ObjectLabel#"+IntegerToString(j);
         long pos=ObjectGetInteger(0,name,OBJPROP_XDISTANCE);
         ObjectSetInteger(0,name,OBJPROP_XDISTANCE,10+j*10+(i&3));
         ObjectSetInteger(0,name,OBJPROP_YDISTANCE,10+j*10+(i&3));
         ObjectSetString(0,name,OBJPROP_TEXT,IntegerToString(MathRand()));
        }
      ChartRedraw(0);
     }
   Print("3. Время обновления текста и позиций у меток со чтением = ",GetTickCount()-start," ms");
//--- переходим к тестам битмапа
   CreateBitmap();
   ChartRedraw(0);
//--- 4. замерим скорость отрисовки меток в канвасе с прозрачностью
   uint   textclr=ColorToARGB(inTextColor);

   name="ObjectBitmap";
   start=GetTickCount();

   for(int i=0;i<inRefreshCount && !IsStopped();i++)
     {
      ArrayInitialize(ExtCanvas,0);
      for(int j=0;j<inNumberOfLabels;j++)
        {
         TextOut(IntegerToString(MathRand()),10+j*10+(i&3),10+j*10+(i&3),TA_LEFT|TA_TOP,ExtCanvas,ExtBitmapWidth,ExtBitmapHeight,textclr,COLOR_FORMAT_ARGB_RAW);
        }
      ResourceCreate("::"+name,ExtCanvas,ExtBitmapWidth,ExtBitmapHeight,0,0,ExtBitmapWidth,COLOR_FORMAT_ARGB_RAW);
      ChartRedraw(0);
     }
   Print("4. Время обновления текста и позиций у битмапа с прозрачностью = ",GetTickCount()-start," ms");
//--- 5. замерим скорость отрисовки меток в канвасе без прозрачности
   start=GetTickCount();

   for(int i=0;i<inRefreshCount && !IsStopped();i++)
     {
      ArrayInitialize(ExtCanvas,ColorToARGB(clrAqua));
      for(int j=0;j<inNumberOfLabels;j++)
        {
         TextOut(IntegerToString(MathRand()),10+j*10+(i&3),10+j*10+(i&3),TA_LEFT|TA_TOP,ExtCanvas,ExtBitmapWidth,ExtBitmapHeight,textclr,COLOR_FORMAT_XRGB_NOALPHA);
        }
      ResourceCreate("::"+name,ExtCanvas,ExtBitmapWidth,ExtBitmapHeight,0,0,ExtBitmapWidth,COLOR_FORMAT_XRGB_NOALPHA);
      ChartRedraw(0);
     }
   Print("5. Время обновления текста и позиций у битмапа без прозрачности = ",GetTickCount()-start," ms");
//--- удалим массив битмапа
   ArrayFree(ExtCanvas);
   Print("Тестирование завершено");
  }
//+------------------------------------------------------------------+
//| Создадим объекты                                                 |
//+------------------------------------------------------------------+
void CreateLabels(void)
  {
//--- удалим все объекты с чарта
   ObjectsDeleteAll(0);
//--- создадим метки
   string name;

   for(int i=0; i<inNumberOfLabels; i++)
     {
      name="ObjectLabel#"+IntegerToString(i);
      if(ObjectCreate(0,name,OBJ_LABEL,0,0,0))
        {
         ObjectSetInteger(0,name,OBJPROP_CORNER,CORNER_LEFT_UPPER);
         ObjectSetInteger(0,name,OBJPROP_ANCHOR,ANCHOR_LEFT_UPPER);
         ObjectSetInteger(0,name,OBJPROP_XDISTANCE,10+i*10);
         ObjectSetInteger(0,name,OBJPROP_YDISTANCE,10+i*10);
         ObjectSetInteger(0,name,OBJPROP_COLOR,inTextColor);
         ObjectSetInteger(0,name,OBJPROP_SELECTABLE,false);
         ObjectSetInteger(0,name,OBJPROP_FONTSIZE,10);
         ObjectSetString(0,name,OBJPROP_FONT,"Courier New");
         ObjectSetString(0,name,OBJPROP_TEXT,name);
        }
     }
//---
  }
//+------------------------------------------------------------------+
//| Создаем битмап                                                   |
//+------------------------------------------------------------------+
void CreateBitmap(void)
  {
   string name="ObjectBitmap";
//--- удалим все объекты с чарта
   ObjectsDeleteAll(0);
//--- выделим место под битмап, занулим его
   ExtBitmapWidth=20+12*inNumberOfLabels;
   ExtBitmapHeight=20+10*inNumberOfLabels;
   ArrayResize(ExtCanvas,ExtBitmapWidth*ExtBitmapHeight);
   ArrayInitialize(ExtCanvas,0);
//--- создадим битмап и привяжем ресурс
   ObjectCreate(0,name,OBJ_BITMAP_LABEL,0,0,0);
   ObjectSetString(0,name,OBJPROP_BMPFILE,"::"+name);
//--- выставим размер текста
   TextSetFont("Arial",-90);
  }
//+---------------------------------------------------------------------------------------------------------------------------+
ファイル:
 

ちなみに、透明度のあるなしは、それほど大きな違いではありません。

2013.04.27 18:24:32     BenchmarkLabel__1 (USDCHF,H1)   Тестирование завершено
2013.04.27 18:24:32     BenchmarkLabel__1 (USDCHF,H1)   5. Время обновления текста и позиций у битмапа без прозрачности = 13229 ms
2013.04.27 18:24:19     BenchmarkLabel__1 (USDCHF,H1)   4. Время обновления текста и позиций у битмапа c прозрачностью = 13994 ms
2013.04.27 18:24:05     BenchmarkLabel__1 (USDCHF,H1)   3. Время обновления текста и позиций у меток с чтением = 32229 ms
2013.04.27 18:23:33     BenchmarkLabel__1 (USDCHF,H1)   2. Время обновления текста и позиций у меток без чтения = 10671 ms
2013.04.27 18:23:22     BenchmarkLabel__1 (USDCHF,H1)   1. Время обновления текста у меток без чтения = 10733 ms
2013.04.27 18:23:11     BenchmarkLabel__1 (USDCHF,H1)   0. Время разогрева динамических очередей без визуализации = 187 ms
 
はい、ビデオドライバの効率に依存します。
 
2013.04.27 20:09:37     BenchmarkObjects (EURUSD,M5)    5. Время обновления текста и позиций у битмапа без прозрачности = 12558 ms
2013.04.27 20:09:24     BenchmarkObjects (EURUSD,M5)    4. Время обновления текста и позиций у битмапа с прозрачностью = 12839 ms
2013.04.27 20:09:11     BenchmarkObjects (EURUSD,M5)    3. Время обновления текста и позиций у меток с чтением = 2355 ms
2013.04.27 20:09:09     BenchmarkObjects (EURUSD,M5)    2. Время обновления текста и позиций у меток без чтения = 10655 ms
2013.04.27 20:08:58     BenchmarkObjects (EURUSD,M5)    1. Время обновления текста у меток без чтения = 10359 ms
2013.04.27 20:08:48     BenchmarkObjects (EURUSD,M5)    0. Время разогрева динамических очередей без визуализации = 124 ms

この結果は不思議な感じがします。コードを見てみないとわからない。

しかしそれでも、タグ付けのスピードはビットマップより速い。


テストは、Windows 7 x64の64bit MetaTrader 5で、NVIDIA GeForce GT 330Mの弱いビデオカードで行われました。

 
OSやビデオカードの種類を示す結果を10件収集する必要があります。

1つのチャートをフルスクリーンで開き、インジケータを使用せず、ウィンドウを切り替えたり、ウィンドウを隠したりせずにテストしてください。

このタスクはレンダリングに直接依存するため、極小のウィンドウサイズで最小化、最小化、テストすることは容認できない。

切り替えを行わず、完全に開いたウィンドウで再度テストを実行します。
 
テストはルールに従って行われました。

2013.04.27 19:20:00     OpenCL  Device #0:  GPU NVIDIA Corporation GeForce GT 430 with OpenCL 1.1 (2 units, 1400 MHz, 1023 Mb, version 296.10, rating 159)
2013.04.27 19:19:58     Terminal        MetaTrader 5 build 803 started (MetaQuotes Software Corp.)
WinXP SP3 x86 3 Гц RAM 3 Гб

2013.04.27 19:34:53     BenchmarkLabel__1 (EURUSD,H1)   Тестирование завершено
2013.04.27 19:34:53     BenchmarkLabel__1 (EURUSD,H1)   5. Время обновления текста и позиций у битмапа с прозрачностью = 38672 ms
2013.04.27 19:34:14     BenchmarkLabel__1 (EURUSD,H1)   4. Время обновления текста и позиций у битмапа с прозрачностью = 39140 ms
2013.04.27 19:33:35     BenchmarkLabel__1 (EURUSD,H1)   3. Время обновления текста и позиций у меток со чтением = 128203 ms
2013.04.27 19:31:27     BenchmarkLabel__1 (EURUSD,H1)   2. Время обновления текста и позиций у меток без чтения = 33000 ms
2013.04.27 19:30:54     BenchmarkLabel__1 (EURUSD,H1)   1. Время обновления текста у меток без чтения = 31969 ms
2013.04.27 19:30:22     BenchmarkLabel__1 (EURUSD,H1)   0. Время разогрева динамических очередей без визуализации = 281 ms
2013.04.27 19:30:21     BenchmarkLabel__1 (EURUSD,H1)
 
ポイント5は、透明化せずに読むべき、結論の訂正を忘れました。
 

前回のビルドは794。803を使ったテストはこちら。

2013.04.27 20:59:43     BenchmarkObjects (EURUSD,M1)    5. Время обновления текста и позиций у битмапа без прозрачности = 5101 ms
2013.04.27 20:59:38     BenchmarkObjects (EURUSD,M1)    4. Время обновления текста и позиций у битмапа с прозрачностью = 5195 ms
2013.04.27 20:59:33     BenchmarkObjects (EURUSD,M1)    3. Время обновления текста и позиций у меток с чтением = 4103 ms
2013.04.27 20:59:29     BenchmarkObjects (EURUSD,M1)    2. Время обновления текста и позиций у меток без чтения = 3557 ms
2013.04.27 20:59:25     BenchmarkObjects (EURUSD,M1)    1. Время обновления текста у меток без чтения = 3338 ms
2013.04.27 20:59:22     BenchmarkObjects (EURUSD,M1)    0. Время разогрева динамических очередей без визуализации = 109 ms

できれば、説明してほしい。 実用的 テスト2、3の意味は?

そしてもう一つ質問です。COLOR_FORMAT_ARGB_RAWとCOLOR_FORMAT_ARGB_NORMALIZEの 違いについて簡単に教えて下さい。

 

しかし、その結果は人によって大きく異なる。テストは、Windows 7 x64NVIDIA GeForce 9600GTMT5 build 803で 行いました。

トレーディング、自動売買システム、ストラテジーテストに関するフォーラム

チャート上の単一テキストマークとビットマップのパフォーマンステスト

tol64, 2013.04.27 17:26

ちなみに、透明度のあるなしは、それほど大きな違いではありません。

2013.04.27 18:24:32     BenchmarkLabel__1 (USDCHF,H1)   Тестирование завершено
2013.04.27 18:24:32     BenchmarkLabel__1 (USDCHF,H1)   5. Время обновления текста и позиций у битмапа без прозрачности = 13229 ms
2013.04.27 18:24:19     BenchmarkLabel__1 (USDCHF,H1)   4. Время обновления текста и позиций у битмапа c прозрачностью = 13994 ms
2013.04.27 18:24:05     BenchmarkLabel__1 (USDCHF,H1)   3. Время обновления текста и позиций у меток с чтением = 32229 ms
2013.04.27 18:23:33     BenchmarkLabel__1 (USDCHF,H1)   2. Время обновления текста и позиций у меток без чтения = 10671 ms
2013.04.27 18:23:22     BenchmarkLabel__1 (USDCHF,H1)   1. Время обновления текста у меток без чтения = 10733 ms
2013.04.27 18:23:11     BenchmarkLabel__1 (USDCHF,H1)   0. Время разогрева динамических очередей без визуализации = 187 ms

 

ウィンドウを切り替えて初めて2回のテストを実施

Win XP SP3 )、ATI統合、MT5ビルド787

ところで、MT5で「about」ウィンドウを開いているとき、Alt+Tabキーでターミナルアイコンが表示されないことに気がつきました

 
3回目のテストでグラフがフリーズしてしまうのは私だけでしょうか?