Вопрос о том, как правильно и максимально эффективно инициализировать массив, часто возникает у начинающих и опытных разработчиков. На первый взгляд кажется, что предварительное выделение памяти (указание размера в конструкторе) должно работать быстрее, чем динамическое расширение коллекции. В этой статье мы подробно разберем технические нюансы работы платформы «1С:Предприятие 8» с массивами, проанализируем результаты тестов и определим «золотой стандарт» разработки.
Рассмотрим две основные ситуации, которые чаще всего встречаются в коде. Представим, что нам нужно создать массив из двух элементов и заполнить его ссылками на предопределенные данные.
Вариант 1: Предварительное определение размера
В этом случае мы сразу сообщаем платформе, сколько элементов будет в массиве, и обращаемся к ним по индексу:
Массив = Новый Массив(2);
Массив[0] = ПланыВидовХарактеристик.Субконто.Номенклатура;
Массив[1] = ПланыВидовХарактеристик.Субконто.Склад;
Вариант 2: Динамическое добавление
Здесь мы создаем пустой объект и последовательно увеличиваем его размер с помощью встроенного метода:
Массив = Новый Массив;
Массив.Добавить(ПланыВидовХарактеристик.Субконто.Номенклатура);
Массив.Добавить(ПланыВидовХарактеристик.Субконто.Склад);
Чтобы выяснить, есть ли реальная разница в скорости работы, обратимся к результатам нагрузочного тестирования. Если на двух элементах разница незаметна, то на 100 000 итераций она должна проявиться. Разберем код теста:
// Тест динамического добавления
МассивДанных = Новый Массив();
Для Инд = 1 По 100000 Цикл
МассивДанных.Добавить(ПланыВидовХарактеристик.ВидыСубконто.Номенклатура);
КонецЦикла;
// Тест обращения по индексу
МассивДанных = Новый Массив(100000);
Для Инд = 1 По 100000 Цикл
МассивДанных[Инд-1] = ПланыВидовХарактеристик.ВидыСубконто.Номенклатура;
КонецЦикла;
Практические замеры показывают, что разница во времени выполнения этих двух циклов находится в пределах погрешности. Почему так происходит? В отличие от языков программирования низкого уровня, в 1С механика выделения памяти под массив работает по принципу «блочного резервирования». Платформа выделяет память не под каждый новый элемент, а сразу под группу. Это минимизирует количество тяжелых операций перераспределения памяти (realloc) при использовании метода Добавить().
Важно понимать внутреннюю логику работы конструктора Новый Массив(N). Когда мы пишем Новый Массив(100), платформа выполняет следующие действия:
Неопределено.Затем, когда мы начинаем заполнять массив данными через Массив[Индекс] = Значение, мы фактически перезаписываем уже существующие данные. Таким образом, вариант с предварительным указанием размера заставляет платформу делать лишнюю работу по инициализации ячеек значениями по умолчанию. В случае же с Добавить() запись значения в память происходит ровно один раз.
С точки зрения стандартов разработки «1С», вариант №2 (через Добавить) является предпочтительным по нескольким причинам:
Инд - 1).Единственный случай, когда первый вариант оправдан и даже необходим — это работа с многомерными массивами. Если нам нужно создать матрицу (массив массивов), удобнее сделать это одной строкой:
// Создаем матрицу 10 на 10
МногомерныйМассив = Новый Массив(10, 10);
Попытка реализовать это через вложенные циклы и методы Добавить() сделает код громоздким и менее понятным для коллег.
Если ваша цель — максимальная оптимизация, рассмотрим еще два полезных инструмента, упомянутых экспертами:
1. ФиксированныйМассив
Если после создания массива вы планируете только читать из него данные, рекомендуется преобразовать его в ФиксированныйМассив. Это особенно полезно при передаче данных между клиентом и сервером, так как такие объекты защищены от записи и могут обрабатываться платформой эффективнее.
Массив = Новый Массив;
Массив.Добавить(ПланыВидовХарактеристик.Субконто.Номенклатура);
ФиксМассив = Новый ФиксированныйМассив(Массив);
2. Метод СтрРазделить
Если вам нужно заполнить массив строковыми значениями (например, из списка, разделенного запятыми), использование встроенной функции СтрРазделить будет работать в несколько раз быстрее любого цикла, так как эта функция реализована на уровне ядра платформы.
СписокИмен = "Номенклатура,Склад,Организация";
МассивИмен = СтрРазделить(СписокИмен, ",");
Проанализировав ситуацию, мы можем сделать вывод: в 1С «борьба за наносекунды» при инициализации массивов не имеет практического смысла. Время, затраченное на один запрос к базе данных или обращение к метаданным, в тысячи раз превышает разницу между Добавить() и Массив[Индекс]. Используйте метод Добавить() как основной способ работы — это сделает ваш код чище, безопаснее и соответствующим стандартам фирмы «1С».