Статья выглядит очень спорной (только пара моментов).
Что за класс вы здесь упомянули?
// Переменная-член класса - created once double prices[]; void OnTick() { // Повторное использование существующего массива for(int i = 0; i < 1000; i++) { prices[i] = iClose(_Symbol, PERIOD_M1, i); } // Обработайте данные... }
Из наличия обработчика OnTick и способа доступа к массиву следует, что вы добавили массив цен в глобальную область видимости, что является плохой идеей (из-за загрязнения пространства имен, если массив нужен только в области видимости обработчика). Вероятно, было бы правильнее сохранить исходный код из того же примера, но сделать массив статическим, чтобы все ясно видели разницу:
// Эффективный подход (выделяет массив один раз, при необходимости может корректировать его размер) void OnTick() { // Это НЕ create (nor allocate) array on every tick static double prices[]; ArrayResize(prices, 1000); // Заполните массив данными о ценах for(int i = 0; i < 1000; i++) { prices[i] = iClose(_Symbol, PERIOD_M1, i); } // Обработайте данные... }
Также, если заменить массив структур (AoS) на структуру массивов (SoA) для OHLCV - доступ к ценам одного и того же бара требует больше ссылок (переключение между массивами вместо увеличения смещения внутри одной структуры) и замедляет процесс, но такие операции встречаются очень часто.
Для данного примера с OHLCV, чтобы повысить эффективность использования памяти и времени, было бы, вероятно, интереснее упаковать все значения в один двумерный или даже одномерный массив:
double TOHLCV[][6];
Это возможно, поскольку все значения типов (double, datetime, long) имеют одинаковый размер 8 байт и могут быть приведены друг к другу напрямую.
Для данного примера с OHLCV, чтобы сделать его более подходящим для экономии памяти и времени, вероятно, было бы интереснее упаковать все значения в один двумерный или даже одномерный массив:
2D массив вместо массива структур может немного сэкономить процессорное время, но значительно увеличит время разработчика на разработку и поддержку кода. По моему личному мнению, я согласен с остальными вашими утверждениями.
https://www.mql5.com/ru/articles/17693#sec2
Давайте рассмотрим проблемный пример:
// Неэффективный подход - создает новые массивы на каждом тике void OnTick() { // Это создает новый массив на каждом тике double prices[]; ArrayResize(prices, 1000); // Заполните массив данными о ценах for(int i = 0; i < 1000; i++) { prices[i] = iClose(_Symbol, PERIOD_M1, i); } // Обработайте данные... // Массив в конце концов будет собран, но это // создает ненужную возню в памяти }
Более эффективным подходом было бы:
// Переменная-член класса - создается один раз double prices[]; void OnTick() { // Повторное использование существующего массива for(int i = 0; i < 1000; i++) { prices[i] = iClose(_Symbol, PERIOD_M1, i); } // Обработайте данные... }
Статья выглядит очень спорной (всего пара моментов).
Что за класс вы здесь упомянули?
Из наличия обработчика OnTick и способа доступа к массиву следует, что вы добавили массив цен в глобальную область видимости, что является плохой идеей (из-за загрязнения пространства имен, если массив нужен только в области видимости обработчика). Вероятно, было бы правильнее сохранить исходный код из того же примера, но сделать массив статическим, чтобы все ясно видели разницу:
Насколько я понимаю, тот пример (я его цитировал выше) - это, грубо говоря, псевдокод, то есть автор не обращает внимания на следующее (чтобы сосредоточиться на том, о чем именно он говорит, я полагаю):
- Судя по условию цикла, размер массива известен во время компиляции, но, тем не менее, массив динамический.
- Несмотря на то, что массив динамический, в коде, демонстрирующем эффективный подход, ArrayResize не вызывался.
- С точки зрения эффективности, я подозреваю, что было бы лучше заменить весь следующий цикл одним вызовом CopySeries:
// Повторное использование существующего массива for(int i = 0; i < 1000; i++) { prices[i] = iClose(_Symbol, PERIOD_M1, i); }
С точки зрения эффективности, я подозреваю, что было бы лучше заменить весь следующий цикл одним вызовом CopySeries:
Поправьте меня, если я ошибаюсь, но, насколько я помню, каждый вызов iClose содержит вызов CopySeries под капотом.
Эта статья содержит глубокий и заставляющий задуматься материал для обсуждения.
Техническое изложение ясное и хорошо объясненное, что позволяет читателю легко следить за ним и оставаться вовлеченным.
Большое спасибо.
В подобных статьях нужны мотивирующие сравнительные тесты, реально показывающие эффективность предлагаемых подходов.
Перевод кривоват, без разбора кода не просто воспринимается.
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Опубликована статья Передовые методы управления и оптимизации памяти в MQL5:
Несомненно, MQL5 — мощный язык, но эта мощь поставляется в комплекте с ответственностью, особенно когда речь идет о памяти. Многие разработчики сосредотачиваются исключительно на логике стратегии, точках входа и управлении рисками, в то время как обработка памяти на заднем плане незаметно превращается в бомбу замедленного действия. По мере увеличения масштабности вашего кода — обработки большего количества символов и более объемных наборов данных — игнорирование памяти может привести к узким местам в производительности, к нестабильности и упущенным возможностям.
В этой статье мы рассмотрим, как все это работает с точки зрения внутренней структуры. Рассмотрим, как в действительности работает память в MQL5, распространенные ловушки, которые замедляют ваши системы или приводят их к сбоям, и — самое важное! — как их исправить. Вы изучите практические методы оптимизации, которые сделают ваши торговые программы быстрее, эффективнее и надежнее.
Вот где эффективное использование памяти действительно имеет значение:
Высокочастотная торговля: каждая миллисекунда — это потенциальное преимущество или потенциальная потеря.
Анализ на нескольких таймфреймах: комбинирование графиков? Ожидайте, что нагрузка на память увеличится в разы.
Тяжелая логика индикаторов: сложные математические расчеты и большие наборы данных могут все застопорить, если ими не управлять.
Тестирование на исторических данных больших объемов: без продуманной оптимизации, тесты на истории могут напоминать наблюдение за высыханием краски.
Если вы готовы всерьез заняться производительностью, давайте углубимся в это — и сделаем ваши MQL5-системы настолько же эффективными, насколько они интеллектуальны.
Автор: Sahil Bagdi