Внутреннее устройство массива в 1С:Предприятие: массив или связный список?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Вопрос о том, как именно организован Массив в платформе 1С:Предприятие, не является чисто академическим. От понимания того, как данные располагаются в оперативной памяти, напрямую зависит производительность наших алгоритмов, особенно когда речь идет о сотнях тысяч или миллионах элементов. В этой статье мы проанализируем технические нюансы реализации этого объекта, разберем механизмы управления памятью и выясним, как платформа оптимизирует работу с коллекциями.

Теоретическая разница: Массив против Связного списка

Прежде чем углубляться в специфику 1С, давайте кратко вспомним теорию структур данных, чтобы понимать, что именно мы ищем. Проанализируем два основных способа хранения последовательностей:

  1. Массив (Array/Vector): Хранится в памяти как непрерывный блок. Это позволяет процессору мгновенно вычислять адрес любого элемента по его индексу. Операция доступа имеет сложность O(1). Однако вставка в начало или середину требует физического сдвига всех последующих элементов.
  2. Связный список (Linked List): Каждый элемент — это отдельный узел, который содержит само значение и указатель на следующий (и иногда предыдущий) узел. Узлы могут быть разбросаны по всей оперативной памяти. Это делает вставку быстрой, но доступ по индексу превращается в медленный перебор всех элементов с начала (сложность O(n)).

Рассмотрим ситуацию: если бы Массив в 1С был связным списком, то цикл по индексу для миллионного элемента работал бы в миллион раз медленнее, чем для первого. На практике в 1С доступ по индексу к любому элементу происходит практически за одинаковое время, что сразу дает нам ключ к разгадке.

Физическая реализация: Динамический массив указателей

Проанализируем структуру Массив в 1С более детально. На уровне ядра платформы (написанного на C++) Массив представляет собой структуру, максимально близкую к std::vector. Это динамический массив типизированных указателей.

Что это означает на практике? В памяти выделяется последовательный блок под массив структур типа Variant (или их аналогов CValue в терминах 1С). Каждая такая структура имеет фиксированный размер (обычно 16–24 байта). Она не содержит само значение (например, длинную строку или тяжелый объект), а хранит:

Именно поэтому Массив в 1С является универсальным: в нем могут одновременно храниться и числа, и огромные таблицы значений. В самом массиве лежат лишь "карточки" фиксированного размера, ссылающиеся на данные в "куче" (heap).

Как 1С выделяет память: Кванты и Capacity

Выясним, почему добавление элементов в Массив происходит быстро, даже если мы не знаем итоговый размер заранее. Платформа использует стратегию экспоненциального резервирования. Разберем этот процесс по шагам:

Когда вы создаете новый Массив и начинаете добавлять в него элементы через метод Добавить(), платформа не выделяет память под каждый чих. Рассмотрим пример:


СписокИмен = Новый Массив;
Для Счетчик = 1 По 100000 Цикл
    СписокИмен.Добавить("Пользователь " + Счетчик);
КонецЦикла;

Внутри платформы происходит следующее: Во-первых, выделяется начальный буфер (например, на 8 или 16 элементов). Это называется Capacity (Емкость). Во-вторых, когда вы добавляете 17-й элемент и места в буфере больше нет, платформа совершает операцию реаллокации. Она выделяет новый блок памяти, который обычно в 1.5 или 2 раза больше предыдущего. В-третьих, старые указатели копируются в новый блок, а старая память освобождается.

Благодаря тому, что объем памяти растет в геометрической прогрессии, количество таких "тяжелых" перераспределений памяти ничтожно мало по сравнению с общим количеством операций добавления. Это делает среднее время добавления (амортизированную сложность) равным O(1).

Производительность различных операций

Посмотрим на эффективность работы с массивом в зависимости от решаемой задачи. Это поможет нам писать более качественный код:

  1. Добавление в конец (метод Добавить()): Очень эффективно. Используется свободная емкость (Capacity).
  2. Вставка в середину (метод Вставить()): Затратно. Платформе приходится физически сдвигать все последующие элементы в памяти, чтобы освободить ячейку. Чем ближе к началу вы вставляете элемент, тем дольше будет работать операция.
  3. Удаление из середины (метод Удалить()): Аналогично вставке — требует сдвига "хвоста" массива для устранения пустоты.
  4. Доступ по индексу: Мгновенно. Прямое вычисление адреса в памяти.

Оптимизация при передаче параметров

Важно понимать, как Массив ведет себя при передаче в процедуры и функции. Рассмотрим ситуацию:


Процедура ОбработатьДанные(МойМассив)
    // Какие-то действия
КонецПроцедуры

// Вызов
ОбработатьДанные(ОгромныйМассив);

В 1С Массив является объектом, поэтому он всегда передается по ссылке. Это значит, что при вызове функции не происходит физического копирования всех элементов в памяти. Копируется только указатель на структуру управления массивом. Это позволяет передавать массивы из миллионов элементов между процедурами практически мгновенно.

Массив против СпискаЗначений: в чем разница?

Часто программисты путают Массив и СписокЗначений. Проанализируем их внутренние различия. В то время как Массив — это максимально легкая и быстрая структура "только для данных", СписокЗначений — это гораздо более сложный объект визуального интерфейса.

Каждый элемент СпискаЗначений дополнительно хранит:

С точки зрения памяти СписокЗначений гораздо тяжелее. Если вам нужно просто хранить набор идентификаторов для обработки в коде, всегда выбирайте Массив — это сэкономит оперативную память и ускорит выполнение кода.

Подведем итоги

Мы выяснили, что Массив в 1С — это классический динамический массив. Он не является связным списком, что гарантирует высокую скорость доступа к данным. Платформа берет на себя все низкоуровневые операции по управлению памятью, используя квантование и резервирование емкости.

Основные выводы для разработки:

← На главную