Как оптимизировать потребление оперативной памяти при формировании больших отчетов в 1С?

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

При работе с большими объемами данных в 1С программисты часто сталкиваются с ситуацией, когда отчет, работающий корректно на небольших периодах, «съедает» всю доступную оперативную память при попытке сформировать его за год или несколько лет. Особенно остро эта проблема стоит для 32-битных клиентских приложений, где лимит адресного пространства ограничен 3.5–4 Гб. Рассмотрим подробнее, почему это происходит и как мы можем эффективно управлять ресурсами системы, не прибегая к радикальной смене архитектуры.

Анализируем объем выходных данных

Первым делом проанализируем, что именно занимает память: сами данные в оперативной памяти (результаты запросов) или итоговый визуальный объект. Разберем ситуацию: если отчет формируется быстро, но после этого память не освобождается, основная нагрузка может лежать на объекте ТабличныйДокумент.

Для диагностики рекомендуется сохранить полученный результат в файл на диск. Если файл весит несколько сотен мегабайт, то в оперативной памяти (в объектном виде) он будет занимать в 5-10 раз больше места. Если ТабличныйДокумент слишком велик, никакая оптимизация запросов не поможет — нужно либо ограничивать выборку, либо использовать постраничный вывод.

Управление данными расшифровки

Одной из самых частых причин «раздувания» памяти в Системе компоновки данных (СКД) являются данные расшифровки. По умолчанию СКД сохраняет во временном хранилище подробную информацию о каждой ячейке, чтобы пользователь мог дважды кликнуть по ней и получить детализацию.

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


// При программном выводе отчета передаем пустое значение вместо объекта расшифровки
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки, Истина);
// Если расшифровка не нужна, можно просто не инициализировать переменную ДанныеРасшифровки

Важно помнить, что даже если флаг расшифровки снят в настройках, 1С может продолжать кэшировать некоторые структуры. Поэтому явное обнуление переменной ДанныеРасшифровки после вывода отчета — хороший тон программирования.

Перенос вычислений на сторону сервера

В «обычном приложении» (Толстый клиент) выполнение кода по умолчанию происходит на стороне клиента. Это означает, что все данные запроса перекачиваются с сервера на клиентский компьютер, где СКД начинает их группировать и оформлять. Выясним причину падения: клиентский процесс x32 просто не справляется с объемом.

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

  1. На сервер передаются только настройки (компоновщик настроек).
  2. На сервере (который обычно является 64-битным) формируется ТабличныйДокумент.
  3. На клиент возвращается уже готовый визуальный объект.

Это позволяет использовать всю мощь серверного оборудования и обходить ограничения клиентской операционной системы.

Оптимизация работы с временными таблицами

Если в вашем отчете используются сложные запросы с менеджером временных таблиц, важно следить за временем жизни этих таблиц. Временные таблицы хранятся в базе данных (TempDB), но ссылки на них и их метаданные удерживаются в объекте МенеджерВременныхТаблиц в оперативной памяти.

Посмотрим на пример правильного завершения работы с данными:


МенеджерВТ = Новый МенеджерВременныхТаблиц;
Запрос.МенеджерВременныхТаблиц = МенеджерВТ;
// ... выполнение запросов ...
// После того как данные получены и переданы в СКД:
МенеджерВТ.Закрыть(); 

Метод Закрыть() принудительно удаляет временные таблицы, не дожидаясь закрытия формы или уничтожения переменной сборщиком мусора.

Влияние условного оформления

Проанализируем неочевидный фактор — Условное оформление. В СКД часто используют раскраску строк, выделение отрицательных чисел красным или изменение шрифта по условию. Для каждого такого случая платформа создает внутренние объекты оформления. Если у вас 500 000 строк и в каждой проверяется условие оформления, это может занять сотни мегабайт памяти.

Рекомендуем придерживаться следующих правил:

Механизм порционного вывода

Если отчет за 4 года категорически не помещается в память, разберем стратегию «разделяй и властвуй». Вместо формирования одного огромного отчета одним вызовом ПроцессорВывода.Вывести(), мы можем реализовать цикл по периодам (например, по годам).

Рассмотрим алгоритм:

  1. Создаем итоговый ТабличныйДокумент.
  2. В цикле за каждый год формируем отдельный отчет программно.
  3. Присоединяем результат к итоговому документу методом Вывести().
  4. После каждой итерации обнуляем временные переменные СКД и вызываем очистку (присваиваем Неопределено).

Такой подход позволяет платформе 1С частично высвобождать память в промежутках между обработкой больших массивов данных.

Принудительная очистка памяти

В языке 1С нет прямого метода для принудительного вызова сборщика мусора, как в некоторых других языках программирования. Однако мы можем «подсказать» системе, что объекты больше не нужны. Для этого всем крупным переменным (результаты запросов, таблицы значений, объекты компоновки) следует присваивать значение Неопределено сразу после того, как они перестали использоваться в коде.

Особое внимание уделите переменным в модуле формы. Если отчет сформирован, данные хранятся в переменных модуля до тех пор, пока форма не будет закрыта. Выясним, можно ли очистить их раньше: да, сразу после вывода результата в поле табличного документа на форме, очистите все промежуточные коллекции данных.

Соблюдение этих рекомендаций позволит значительно повысить стабильность работы отчетов и избежать критических ошибок "Out of memory" даже на значительных объемах данных.

← На главную