Вчера открыв Каталог данных не заметил как папка Indicators переместилась в папку Experts. Потом выключил мт5 и уже сегодня включил, индикаторы также можно использовать из Навигатора, как ни в чем не бывало. Но, если обратно открыть Каталог данных то там появится пустая папка Indicators и если уже в нее кинуть какой-то индикатор. То он уже не появится в Навигаторе. Возврат папки Indicators обратно в MQL5\Indicators решает проблему.
МТ5 (build 2347) Почему такой большой overhead при добавлении по одному элементу в массив с помощью ArrayResize, если память для них была заранее зарезервирована?
Прошу рассмотреть возможность улучшения внутреннего алгоритма резервирования с помощью ArrayResize.
Например, для классов можно припустить, что они кроме вызова конструктора выполняют некую "внутреннюю регистрацию в списках". И в рамках резервирования с помощью ArrayResize, кроме непосредственного выделения памяти, можно попробовать оптимизировать процесс: - брать данные из соседнего созданного элемента (например указатель на таблицу виртуальных функций); - заранее выполнять или резервировать место под "внутреннюю регистрацию" классов, которые еще не созданы;
МТ5 (build 2347) Почему такой большой overhead при добавлении по одному элементу в массив с помощью ArrayResize, если память для них была заранее зарезервирована?
Даже такое не помогает.
ArrayResize(class_array, 1, array_size - 1);
for(int i = 0; i < array_size; i++){
// ArrayResize(class_array, i);ArrayResize(class_array, i, array_size - 1);
--- Test Fast: ArrayResize(arr,100000,100000)
1. ArraySize(arr)=100000 Time=0 ms
2. ArraySize(arr)=200000 Time=0 ms
3. ArraySize(arr)=300000 Time=0 ms
---- Test Slow: ArrayResize(slow,100000)
1. ArraySize(slow)=100000 Time=0 ms
2. ArraySize(slow)=200000 Time=0 ms
При успешном выполнении функция возвращает количество всех элементов, содержащихся в массиве после изменения размера; в противном случае возвращает -1 и массив не меняет размеры. Если ArrayResize() применена к статическому массиву, таймсерии или индикаторному буферу, то размер массива остается прежним – такие массивы не могут быть...
Sergey Dzyublik : Поработал с профайлером в МТ5 (build 2345), грубо говоря, интересовало почему два алгоритма, дающих в конечном итоге один и тот же результат, выполняются с разной скоростью, просадка в 1.7 раза в режиме оптимизации .
...
К сожалению, это долгое время профилировщик бесполезен для любого важного проекта. Я уже пытался сообщить об этом, но не было никакого интереса со стороны разработчиков.
МТ5 (build 2347) Почему такой большой overhead при добавлении по одному элементу в массив с помощью ArrayResize, если память для них была заранее зарезервирована?
Если вы хотите сравнить, это должно быть:
voidtest1 ( constint test_count, constint array_size){
SpeedTest(
test_count,"Test Class ArrayResize all",
{
T class_array[];
for ( int i = 0 ; i < array_size; i++){
ArrayResize (class_array, i );
}
}
)
С моей стороны сравнивалось то, что должно было быть. Мне известно сколько элементов будет помещено в массив и вместо того, что бы создавать их все сразу - резервирую память под несозданные. Проблема в том, что если резервирую память, а создаю элементы массива по одному, то это требует в разы больше времени, чем просто создать все сразу. Так для стуктур - это в 7 раз медленнее. А для типов данных класс и int - в два раза медленнее.
Это очень большая разница, которую, как мне кажется, при желании разработчики могут устранить.
Не заметил этого в коде. Тогда объяснимо, т.к. там только один if срабатывает, где если размер не поменялся, выходим.
Пояснение относительно приведенного выше кода #26666
test1, создает все элементы стразу при первом вызове, остальные вызовы ArrayResize идут в "холостую". Общее количество вызовов ArrayResize == array_size:
T class_array[];
for(int i = 1; i <= array_size; i++){
ArrayResize(class_array, array_size);
}
test2, создает один элемент и резервирует место еще для array_size-1 элемент, остальные вызовы ArrayResize идут для создании +1 элемента в массиве из ранее зарезервированной памяти. Общее количество вызовов ArrayResize == array_size:
T class_array[];
ArrayResize(class_array, 1, array_size - 1);
for(int i = 2; i <= array_size; i++){
ArrayResize(class_array, i);
}
* в изначальном коде была ошибка (разница +- один элемент). Код обновлен. Вопрос остается открытым: почему алгоритм test2 медленнее test1 для структур в 7 раз, а для классов и int - в 2 раза?
С моей стороны сравнивалось то, что должно было быть. Мне известно сколько элементов будет помещено в массив и вместо того, что бы создавать их все сразу - резервирую память под несозданные. Проблема в том, что если резервирую память, а создаю элементы массива по одному, то это требует в разы больше времени, чем просто создать все сразу. Так для стуктур - это в 7 раз медленнее. А для типов данных класс и int - в два раза медленнее.
Это очень большая разница, которую, как мне кажется, при желании разработчики могут устранить.
Хорошо в этом случае, я согласен, что должны быть только меньшие накладные расходы.
Но, на мой взгляд, проблема скорее в том, как вы сравниваете. Цикл в test1, скорее всего, оптимизирован и удален компилятором, и, возможно, даже следующим:
for ( ulong ii= 0 ;ii<count&&! _StopFlag ;ii++)
Попробуйте профилировщик, и вы увидите только небольшую разницу.
Это скорее не баг, а замечание!
мт 5 билд 2340.
Вчера открыв Каталог данных не заметил как папка Indicators переместилась в папку Experts. Потом выключил мт5 и уже сегодня включил, индикаторы также можно использовать из Навигатора, как ни в чем не бывало. Но, если обратно открыть Каталог данных то там появится пустая папка Indicators и если уже в нее кинуть какой-то индикатор. То он уже не появится в Навигаторе. Возврат папки Indicators обратно в MQL5\Indicators решает проблему.
МТ5 (build 2347) Почему такой большой overhead при добавлении по одному элементу в массив с помощью ArrayResize, если память для них была заранее зарезервирована?
Прошу рассмотреть возможность улучшения внутреннего алгоритма резервирования с помощью ArrayResize.
Например, для классов можно припустить, что они кроме вызова конструктора выполняют некую "внутреннюю регистрацию в списках".
И в рамках резервирования с помощью ArrayResize, кроме непосредственного выделения памяти, можно попробовать оптимизировать процесс:
- брать данные из соседнего созданного элемента (например указатель на таблицу виртуальных функций);
- заранее выполнять или резервировать место под "внутреннюю регистрацию" классов, которые еще не созданы;
МТ5 (build 2347) Почему такой большой overhead при добавлении по одному элементу в массив с помощью ArrayResize, если память для них была заранее зарезервирована?
Даже такое не помогает.
Ерунда какая-то. Вместо ускорения тормоза.
ЗЫ Странно, результат выполнения примера из Документации нулевой.
Поработал с профайлером в МТ5 (build 2345),
грубо говоря, интересовало почему два алгоритма, дающих в конечном итоге один и тот же результат, выполняются с разной скоростью, просадка в 1.7 раза в режиме оптимизации .
...
МТ5 (build 2347) Почему такой большой overhead при добавлении по одному элементу в массив с помощью ArrayResize, если память для них была заранее зарезервирована?
Если вы хотите сравнить, это должно быть:
Если вы хотите сравнить, это должно быть:
С моей стороны сравнивалось то, что должно было быть.
Мне известно сколько элементов будет помещено в массив и вместо того, что бы создавать их все сразу - резервирую память под несозданные.
Проблема в том, что если резервирую память, а создаю элементы массива по одному, то это требует в разы больше времени, чем просто создать все сразу.
Так для стуктур - это в 7 раз медленнее.
А для типов данных класс и int - в два раза медленнее.
Это очень большая разница, которую, как мне кажется, при желании разработчики могут устранить.
Проблема в том, что если резервирую память, а создаю элементы массива по одному, то это требует в разы больше времени, чем просто создать все сразу.
Не заметил этого в коде. Тогда объяснимо, т.к. там только один if срабатывает, где если размер не поменялся, выходим.
Не заметил этого в коде. Тогда объяснимо, т.к. там только один if срабатывает, где если размер не поменялся, выходим.
Пояснение относительно приведенного выше кода #26666
test1, создает все элементы стразу при первом вызове, остальные вызовы ArrayResize идут в "холостую".
Общее количество вызовов ArrayResize == array_size:
test2, создает один элемент и резервирует место еще для array_size-1 элемент, остальные вызовы ArrayResize идут для создании +1 элемента в массиве из ранее зарезервированной памяти.
Общее количество вызовов ArrayResize == array_size:
* в изначальном коде была ошибка (разница +- один элемент). Код обновлен.
Вопрос остается открытым: почему алгоритм test2 медленнее test1 для структур в 7 раз, а для классов и int - в 2 раза?
С моей стороны сравнивалось то, что должно было быть.
Мне известно сколько элементов будет помещено в массив и вместо того, что бы создавать их все сразу - резервирую память под несозданные.
Проблема в том, что если резервирую память, а создаю элементы массива по одному, то это требует в разы больше времени, чем просто создать все сразу.
Так для стуктур - это в 7 раз медленнее.
А для типов данных класс и int - в два раза медленнее.
Это очень большая разница, которую, как мне кажется, при желании разработчики могут устранить.
Хорошо в этом случае, я согласен, что должны быть только меньшие накладные расходы.
Но, на мой взгляд, проблема скорее в том, как вы сравниваете. Цикл в test1, скорее всего, оптимизирован и удален компилятором, и, возможно, даже следующим:
Попробуйте профилировщик, и вы увидите только небольшую разницу.
Нет оптимизации компилятора с помощью профилировщика.