* Оптимизация. Пул массивов.
При разработке скриптов приходится работать с большими массивами данных. Создание и удаление больших массивов трудозатратный процесс. Если в скрипте часто создаются большие массивы, то загрузка процессора может просесть, что сказывается на времени оптимизации.
Чтобы этого избежать, можно использовать внутренний пул массивов в TSLab. Это работает только для оптимизации.
Пул массивов - это коллекция массивов, которые находятся в памяти. Например, запускаем оптимизацию скрипта. В скрипте запрашиваем новый массив из пула. Пул ищет у себя подходящий свободный массив, по типу и длине данных. Если такого массива в пуле нет, то он создается. Далее скрипт помещает в этот массив свои данные, производит вычисления, выводит их на график если надо. После выполнения скрипта контекст данных освобождается, и все массивы из пула, которые были использованы в этом контексте, очищаются и помещаются обратно в пул. Далее, при проходе следующего итерации оптимизации, скрипт запрашивает массив из пула и действия повторяются. Таким образом, сокращается количество создаваемых массивов.
При освобождении контекста массив будет помещаться обратно в пул, только если он не закеширован.
Методы:
T[] IContext.GetArray<T>(int count) – получить массив с типом T и количеством элементов count из пула. Если в пуле нет такого массива, то он создается.
void ReleaseArray(Array array) – передать обратно массив в пул. При этом массив очищается. Метод ReleaseArray вызывается автоматически при освобождении контекста (IContext), после прохода оптимизации (если массив не был помещен в кеш).
Рассмотрим пример. Создадим массив с double числами, поместим в него среднюю цену бара и в конце выведем в лог хеш-код этого объекта.
Теперь проведем оптимизацию, только в настройках TSLab поставим 'Количество потоков оптимизации' равное 1. Это нужно чтобы проверить как часто у нас создается новый массив. Так как указали количество потоков 1, то сначала пройдет один проход итерации, потом второй и так далее, друг за другом. В логе мы видим разные значения хеш-кодов. Это означает, что при каждом проходе оптимизации создавался новый массив.
Теперь мы немного изменим наш пример, вместо создания массива будем получать его из пула: var arr = ctx.GetArray<double>(bars.Count);
Запускаем оптимизацию, снова с одним потоком. В логе мы видим одинаковый хеш-код. Это означает что во всех итерациях оптимизации использовался только один массив. Мы брали его из пула, использовали, при завершении итерации он помещался обратно в пул. При следующей итерации мы снова берем этот же массив из пула.
Что будет если в настройках поставить максимальное количество потоков и запустить оптимизацию на 10000 проходов? Оптимизация запустится на всех имеющихся потоках процессора. При каждой итерации будет браться массив из пула, обрабатываться и помещаться обратно в пул. Но так как потоков теперь у нас много, то теперь одного массива в пуле на всех не хватит. В этом случае будут созданы дополнительные массивы в пуле. И в конце оптимизации окажется что количество массивов в пуле равно количеству потоков. Хотя проходов у нас было 10000.
Во многих стандартных блоках TSLab используется пул массивов. Например блок расчета ATR:
Заметка: Пул потоков в TSLab это аналог ArrayPool из .NET Core.