Вы упускаете торговые возможности:
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Регистрация
Вход
Вы принимаете политику сайта и условия использования
Если у вас нет учетной записи, зарегистрируйтесь
Спасибо С-4 за ответ. Особенно насчет большого времени на изменение размеров массивов.
По поводу глобальных / локальных переменных решил поставить эксперимент. Написал такую функцию
void OnTick()
{
// 29 c - на глобальных переменных
v1=1.212;
v2=1001;
for (int i=0;i<20000;i++){
if(v1<v2){v1=v1+1.214;}else{v2=v2*1.1201;}
}
/*
//36 c - на локальных переменных
double v3=1.212;
double v4=1001;
for (int i=0;i<20000;i++){
if(v3<v3){v3=v3+1.214;}else{v4=v4*1.1201;}
}
*/
}
Тут 2 участка кода один для глобальных, второй для локальных переменных. Комментируя по очереди их делал замер времени работы тестера на промежутке в 7 дней, чтобы было много запусков OnTick()
В результате на глобальных переменных 1 проход занял 29 секунд, на локальных 36 секунд.
Потом уменьшил цикл до 20 for (int i=0;i<20;i++) и запустил проход за последние 2 года, в результате получил одинаковый результат - по 23 секунды и для локальных и для глобальных переменных. Тут объем вычислений мал, 20 сравнений и 20 арифметических операций. Думаю в большинстве советников за 1 тик происходит не больше.
Так что мне кажется не стоит заморачиваться насчет типа переменных - как удобнее и понятнее для программиста - так и надо делать. Ну а если за 1 тик - будут тысячи операций, то получается, что это лучше делать с помощью глобальных переменных.
Локальная переменная создается временно при вызове функции и освобождает память при завершении, а это требует времени.
Глобальная создается один раз при инициализации эксперта или индикатора.
Локальная переменная создается временно при вызове функции и освобождает память при завершении, а это требует времени.
Глобальная создается один раз при инициализации эксперта или индикатора.
Локальная переменная, как правило, размещается на стеке. А значит, ее размещение происходит автоматически при вызове функции, никаких действий по размещению локальная переменная больше не требует.
Глобальная переменная - если имеется ввиду глобальная переменная как "доступная из любого места программы" - то она тоже может быть размещена на стеке программы. Но если имеется ввиду глобальная переменная, которая занимает особую область памяти в терминале - то, да, для ее размещения требуется время, но оно требуется один раз.
Уникальность объекта не зависит от его хеш кода.
Для примера переопределите GetHeshCode() чтобы она всегда возвращала одну и ту же константу для объектов какого-нибудь класса. Подозреваю что вы потом сможете без труда нашпиговать Dictionary любыми объектами данного класса (как Key). А hashtable лежащая в основе словаря просто выродиться в список. GetHeshCode() переопределяют тогда, когда планируют использовать экземпляры объекта как ключи в хеш таблице (как Key). Ни больше ни меньше. И желательно что бы её логика зависела от тех же полей от которых зависит Equals(). Но это не обязательно.
Более того у вас в примере СPerson и SPerson вообще выступают в роли ключей (как Key). Для них ни в каком случае GetHeshCode() не будет вызван, только Equals() на некоторых этапах.
Я не умничаю и не хочу никого задеть, совсем недавно сам больно несколько раз наступал на похожие грабли.
P.S. Ещё есть скользкие кейсы с mutable/immutable ключами, кейсы с зацикливанием при получение хеш кода для комплексных объектов. Но это всё уже и так сильно далеко от "локальных и глобальных переменных"Возможно в С# всё не так ))
P.S.S Вычеркнул чушь
"Преждевременная оптимизация — это корень всех бед" (c) Дональд Кнут
Сначала нормальный код, а потом профайлером по нему.
Тоже плюсую.
Поднятые вопросы настолько далеки от реалий программирования на mql, что смысла их обсуждать нет ни какого.
Разве что про массивы правильно заметили (перераспределение - медленное). Но на это так или иначе наткнешься, немного с ними поработав.
И для ускорения, кстати, совсем не обязательно знать финальный размер, достаточно увеличивать размер массива порциями (например, по 1000 элементов).
В пятерочной функции есть даже специальный параметр для этого:
Тоже плюсую.
Поднятые вопросы настолько далеки от реалий программирования на mql, что смысла их обсуждать нет ни какого.
Разве что про массивы правильно заметили (перераспределение - медленное). Но на это так или иначе наткнешься, немного с ними поработав.
И для ускорения, кстати, совсем не обязательно знать финальный размер, достаточно увеличивать размер массива порциями (например, по 1000 элементов).
В пятерочной функции есть даже специальный параметр для этого:
Да, обычно в классах-массивах так и происходит. В Net например, увеличение массива происходит автоматически, количество элементов выбирается кратным двум, т.е. сначала на 2, потом на 4, 8, 16, 32 и т.д.
А вообще да, мы с обсуждением словарей ушли далеко в оффтоп. Хотя работу функции GetHeshCode() я проверю)
Спасибо С-4 за ответ. Особенно насчет большого времени на изменение размеров массивов.
По поводу глобальных / локальных переменных решил поставить эксперимент. Написал такую функцию
void OnTick()
{
// 29 c - на глобальных переменных
v1=1.212;
v2=1001;
for (int i=0;i<20000;i++){
if(v1<v2){v1=v1+1.214;}else{v2=v2*1.1201;}
}
/*
//36 c - на локальных переменных
double v3=1.212;
double v4=1001;
for (int i=0;i<20000;i++){
if(v3<v3){v3=v3+1.214;}else{v4=v4*1.1201;}
}
*/
}
Тут 2 участка кода один для глобальных, второй для локальных переменных. Комментируя по очереди их делал замер времени работы тестера на промежутке в 7 дней, чтобы было много запусков OnTick()
В результате на глобальных переменных 1 проход занял 29 секунд, на локальных 36 секунд.
Потом уменьшил цикл до 20 for (int i=0;i<20;i++) и запустил проход за последние 2 года, в результате получил одинаковый результат - по 23 секунды и для локальных и для глобальных переменных. Тут объем вычислений мал, 20 сравнений и 20 арифметических операций. Думаю в большинстве советников за 1 тик происходит не больше.
Так что мне кажется не стоит заморачиваться насчет типа переменных - как удобнее и понятнее для программиста - так и надо делать. Ну а если за 1 тик - будут тысячи операций, то получается, что это лучше делать с помощью глобальных переменных.
Облегчаю работу
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
//Ассциируем с каждой личностью ее рейтинг на MQL5:
Dictionary<CPerson, int> DictionaryRaiting = new Dictionary<CPerson, int>();
//А теперь побезобразничаем и нашпигуем словарик разными ключами - личностями (каждый ключ это новый объект),
//возвращающими ОДИН И ТОТ ЖЕ HashCode:
for (int i = 0; i < 5; i++ )
{
DictionaryRaiting.Add(new CPerson("Вася"), 1910);
Console.Out.WriteLine("Dictionary size: " + DictionaryRaiting.Count);
}
Console.ReadKey();
}
}
/// <summary>
/// Личность
/// </summary>
class CPerson
{
public CPerson(string name)
{
mName = name;
}
public string Name
{
get { return mName; }
}
/// <summary>
/// Внутреннее имя человека.
/// </summary>
private string mName;
public override int GetHashCode()
{
Console.Out.WriteLine("GetHashCode() was called and returns 1");
return 1;
}
}
}
Посмотрим на консольку и сделаем вывод