"MQL5 Cookbook: Hızlı Veri Erişimi için İlişkisel Dizi veya Sözlük Uygulama" makalesi için tartışma

 

Yeni makale MQL5 Cookbook: Hızlı Veri Erişimi için İlişkisel Dizi veya Sözlük Uygulama yayınlandı:

Bu makale, benzersiz anahtarlarıyla öğelere erişim elde etmeyi sağlayan özel bir algoritmayı açıklar. Herhangi bir temel veri türü anahtar olarak kullanılabilir. Örneğin bir dize veya bir tamsayı değişkeni olarak temsil edilebilir. Bu tür bir veri taşıyıcısına genellikle sözlük veya ilişkisel dizi denir. Problem çözme için daha kolay ve daha verimli bir yol sağlar.

Gelişigüzel türde öğelere sahip bir dizinin yalnızca bir büyük kusuru vardır: yeni bir öğe eklemek istiyorsanız, özellikle de bu öğenin dizinin ortasına eklenmesi gerekiyorsa çok zaman ve çaba gerektirir. Öğeler bir sıralamada bulunur, bu nedenle ekleme için diziyi yeniden boyutlandırarak toplam öğe sayısını bir artırmanız ve ardından eklenen nesneyi izleyen tüm öğeleri, indeksleri yeni değerlerine karşılık gelecek şekilde yeniden düzenlemeniz gerekmektedir.

7 öğeli bir dizimiz olduğunu ve dördüncü pozisyona bir öğe daha eklemek istediğimizi varsayalım. Yaklaşık bir yerleştirme şeması aşağıdaki gibi olacaktır:

Şek. 2. Dizi yeniden boyutlandırma ve yeni bir öğenin eklenmesi

Şek. 2. Dizi yeniden boyutlandırma ve yeni bir öğenin eklenmesi

Yazar: Vasiliy Sokolov

 

Harika iş, yazara tebrikler! Bu, MQ'nun \MQL5\Include\Arrays'e uzun zaman önce dahil etmesi gereken bir şey, umarım sonraki sürümlerde kütüphaneye dahil edilir. Bu arada, her şey MQL4'te de iyi çalışıyor, işte ilk testten ölçümler. Tam teşekküllü işaretçilerin olmaması nedeniyle *CObject yerine basit veri türlerini dahil etmenin imkansız olduğunu anlıyorum? Ya da bunu aşmanın bir yolu var mı?

2015.03.23 13:25:54.617 TestDict EURUSD,M1: 1000000 elements. Add: 1373; Get: 218
2015.03.23 13:25:52.644 TestDict EURUSD,M1: 950000 elements. Add: 1216; Get: 219
2015.03.23 13:25:50.833 TestDict EURUSD,M1: 900000 elements. Add: 1217; Get: 218
2015.03.23 13:25:49.069 TestDict EURUSD,M1: 850000 elements. Add: 1154; Get: 187
2015.03.23 13:25:47.424 TestDict EURUSD,M1: 800000 elements. Add: 1092; Get: 187
2015.03.23 13:25:45.844 TestDict EURUSD,M1: 750000 elements. Add: 1061; Get: 171
2015.03.23 13:25:44.320 TestDict EURUSD,M1: 700000 elements. Add: 1107; Get: 156
2015.03.23 13:25:42.761 TestDict EURUSD,M1: 650000 elements. Add: 1045; Get: 140
2015.03.23 13:25:41.304 TestDict EURUSD,M1: 600000 elements. Add: 1014; Get: 156
2015.03.23 13:25:39.915 TestDict EURUSD,M1: 550000 elements. Add: 920; Get: 125
2015.03.23 13:25:38.665 TestDict EURUSD,M1: 500000 elements. Add: 702; Get: 109
2015.03.23 13:25:37.693 TestDict EURUSD,M1: 450000 elements. Add: 593; Get: 93
2015.03.23 13:25:36.836 TestDict EURUSD,M1: 400000 elements. Add: 577; Get: 78
2015.03.23 13:25:36.025 TestDict EURUSD,M1: 350000 elements. Add: 561; Get: 78
2015.03.23 13:25:35.247 TestDict EURUSD,M1: 300000 elements. Add: 515; Get: 78
2015.03.23 13:25:34.557 TestDict EURUSD,M1: 250000 elements. Add: 343; Get: 63
2015.03.23 13:25:34.063 TestDict EURUSD,M1: 200000 elements. Add: 312; Get: 47
2015.03.23 13:25:33.632 TestDict EURUSD,M1: 150000 elements. Add: 281; Get: 31
2015.03.23 13:25:33.264 TestDict EURUSD,M1: 100000 elements. Add: 171; Get: 16
2015.03.23 13:25:33.038 TestDict EURUSD,M1: 50000 elements. Add: 47; Get: 16
 
VDev:

Harika iş, yazara tebrikler! Bu, MQ'nun uzun zaman önce MQL5/Include/ Arrays'e dahil etmesi gereken bir şey, umarım sonraki sürümlerde kütüphaneye dahil edilir. Bu arada, her şey MQL4'te de iyi çalışıyor, işte ilk testten ölçümler. Tam teşekküllü işaretçilerin olmaması nedeniyle *CObject yerine basit veri türlerini dahil etmenin imkansız olduğunu anlıyorum? Ya da bunu çalıştırmanın bir yolu var mı?

İşe yarayacaktır. Kutulama/kutudan çıkarma mekanizması ve şablonlar yardımıyla. Buradaki fikir, her temel tipin bir KeyValuePairBase konteynerine paketlenmesidir. Paketin açılması ve ilgili türün döndürülmesi GetObjectByKey türünün dahili fonksiyonları tarafından yapılır:

template<typename Type, typename T>
Type GetObjectByKey(T key);

Temel tiplerle çalışmanın herhangi bir performans avantajı sağlamayacağını, ancak çok daha kullanışlı olacağını vurgulamak önemlidir.

 

Şimdi şablonlar temelinde CObject yerine temel MQL türlerinden birini depolayan bir CDictionaryBase oluşturmayı denedim. Ne yazık ki işe yaramadı, fonksiyonlar bir şablon tipi döndürmeye izin vermiyor. Çok yazık:

//+------------------------------------------------------------------+
//|TestDictBase.mq5 |
//|Telif Hakkı 2015, Vasiliy Sokolov. |
//|http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, Vasiliy Sokolov."
#property link      "http://www.mql5.com"
#property version   "1.00"
#include <Dictionary.mqh>
#include <DictionaryBase.mqh>
//+------------------------------------------------------------------+
//| Komut dosyası programı başlatma işlevi|
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   CDictionaryBase base;
   base.AddValue("Pi", 3.14159);
   double pi = (double)base.GetValueByKey("Pi");
   printf(DoubleToString(pi, 5));
   //base.AddObject(
  }
//+------------------------------------------------------------------+
could not deduce template argument #1    TestDictBase.mq5        19      29
could not deduce template argument #0    DictionaryBase.mqh      404     25
possible loss of data due to type conversion    DictionaryBase.mqh      133     10
possible loss of data due to type conversion    DictionaryBase.mqh      135     10
possible loss of data due to type conversion    DictionaryBase.mqh      137     10
...

//+------------------------------------------------------------------+
//| Nesneyi anahtara göre döndürür.|
//+------------------------------------------------------------------+
template<typename T, typename C>
C CDictionaryBase::GetValueByKey(T key)
  {
   if(!ContainsKey(key))
      return NULL;
   return m_current_kvp.GetValue();
  }

Çok kötü.

Bu nedenle, her temel tip için bir temel kapsayıcı oluşturmamız veya sadece temel tiplerin kapsayıcılarını oluşturmamız gerekecek: CDouble, CLong, CInt, vb.

 
C-4:

Şimdi şablonlar temelinde CObject yerine temel MQL türlerinden birini depolayan bir CDictionaryBase oluşturmaya çalıştım. Ne yazık ki bunu yapamadım, fonksiyonlar bir şablon türü döndürmeye izin vermiyor.

Öyle yaparlar. Ancak döndürülen değerin türü otomatik olarak çıkarılamaz, bu aslında derleyici tarafından yazılır.

Sözde parametre şeklinde küçük bir koltuk değneği kullanabilirsiniz.

template<typename T, typename C>
C CDictionaryBase::GetValueByKey(T key, C)
{
   if(!ContainsKey(key))
      return NULL;
   return m_current_kvp.GetValue();
}
 
TheXpert:

Öyle. Ancak döndürülen değerin türü otomatik olarak çıkarılamaz, bu da derleyicinin gerçekte yazdığı şeydir.

Sözde parametre şeklinde küçük bir koltuk değneği kullanabilirsiniz.

Gerçek koltuk değneği nerede?
 
C-4:
Gerçek koltuk değneği nerede?
İkinci bir parametre eklendi
 
TheXpert:
İkinci bir parametre eklendi
Şimdi görüyorum. Yarın kontrol ederim.
 
Performansı karşılaştırmayı denediniz mi? Sıralanmış bir dize dizisinde ikili aramaya göre avantaj hangi veri boyutunda başlar?
 
Integer:
Performansı karşılaştırmayı denediniz mi? Sıralanmış bir string dizisinde ikili aramaya göre avantaj hangi veri boyutunda başlar?

Kesin testler yapmadım ama gözlemlerime göre hız avantajı onbinlerce elemandan itibaren ortaya çıkmaya başlıyor. Yani 100-10 000 elemanlı günlük işlerde bir performans kazancı elde edilemez.

Burada başka bir şey daha önemli, yani konteyner ile çalışma kolaylığı. Elemanları aramak için ek yöntemler yazmanıza gerek yoktur. Sözlüklerle yapılan birçok günlük işin uygulanması çok daha kolay hale gelir. Bir dizini aramak için bir öğe oluşturmanıza, ardından ilgili dizine göre gerekli olanı almanıza vb. gerek yoktur.

s.s. Yine de burada performansın öğeleri ekleme ve arama için toplam süre olarak ölçülmesi gerektiğini düşündüm. CArrayObj 'de sıralanmış öğeleri aramak oldukça hızlı bir işlemse, ekleme gerçek bir sorundur. Hızlı arama düzenlilik gerektirdiğinden, olası eklemelerden kurtulamayız ve bu performansı önemli ölçüde yavaşlatır.

 

Çok ilginç ve sözlüğün çok yararlı ve kullanımı kolay bir veri düzenleyici olduğu açık.


Paylaşımınız için teşekkürler.